ICRS Eurobot 2013

Dependencies:   mbed mbed-rtos Servo QEI

Committer:
madcowswe
Date:
Sat Apr 06 20:57:54 2013 +0000
Revision:
15:9c5aaeda36dc
Encoders fairly tuned, still has random noise in it

Who changed what in which revision?

UserRevisionLine numberNew contents of line
madcowswe 15:9c5aaeda36dc 1 /*
madcowswe 15:9c5aaeda36dc 2 * Tiny Vector Matrix Library
madcowswe 15:9c5aaeda36dc 3 * Dense Vector Matrix Libary of Tiny size using Expression Templates
madcowswe 15:9c5aaeda36dc 4 *
madcowswe 15:9c5aaeda36dc 5 * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.net>
madcowswe 15:9c5aaeda36dc 6 *
madcowswe 15:9c5aaeda36dc 7 * This library is free software; you can redistribute it and/or
madcowswe 15:9c5aaeda36dc 8 * modify it under the terms of the GNU lesser General Public
madcowswe 15:9c5aaeda36dc 9 * License as published by the Free Software Foundation; either
madcowswe 15:9c5aaeda36dc 10 * version 2.1 of the License, or (at your option) any later version.
madcowswe 15:9c5aaeda36dc 11 *
madcowswe 15:9c5aaeda36dc 12 * This library is distributed in the hope that it will be useful,
madcowswe 15:9c5aaeda36dc 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
madcowswe 15:9c5aaeda36dc 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
madcowswe 15:9c5aaeda36dc 15 * lesser General Public License for more details.
madcowswe 15:9c5aaeda36dc 16 *
madcowswe 15:9c5aaeda36dc 17 * You should have received a copy of the GNU lesser General Public
madcowswe 15:9c5aaeda36dc 18 * License along with this library; if not, write to the Free Software
madcowswe 15:9c5aaeda36dc 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
madcowswe 15:9c5aaeda36dc 20 *
madcowswe 15:9c5aaeda36dc 21 * $Id: Vector.h,v 1.48 2007-06-23 15:58:58 opetzold Exp $
madcowswe 15:9c5aaeda36dc 22 */
madcowswe 15:9c5aaeda36dc 23
madcowswe 15:9c5aaeda36dc 24 #ifndef TVMET_VECTOR_H
madcowswe 15:9c5aaeda36dc 25 #define TVMET_VECTOR_H
madcowswe 15:9c5aaeda36dc 26
madcowswe 15:9c5aaeda36dc 27 #include <iterator> // reverse_iterator
madcowswe 15:9c5aaeda36dc 28
madcowswe 15:9c5aaeda36dc 29 #include <tvmet/tvmet.h>
madcowswe 15:9c5aaeda36dc 30 #include <tvmet/TypePromotion.h>
madcowswe 15:9c5aaeda36dc 31 #include <tvmet/CommaInitializer.h>
madcowswe 15:9c5aaeda36dc 32 #include <tvmet/RunTimeError.h>
madcowswe 15:9c5aaeda36dc 33
madcowswe 15:9c5aaeda36dc 34 #include <tvmet/xpr/Vector.h>
madcowswe 15:9c5aaeda36dc 35
madcowswe 15:9c5aaeda36dc 36 namespace tvmet {
madcowswe 15:9c5aaeda36dc 37
madcowswe 15:9c5aaeda36dc 38
madcowswe 15:9c5aaeda36dc 39 /* forwards */
madcowswe 15:9c5aaeda36dc 40 template<class T, std::size_t Sz> class Vector;
madcowswe 15:9c5aaeda36dc 41
madcowswe 15:9c5aaeda36dc 42
madcowswe 15:9c5aaeda36dc 43 /**
madcowswe 15:9c5aaeda36dc 44 * \class VectorConstReference Vector.h "tvmet/Vector.h"
madcowswe 15:9c5aaeda36dc 45 * \brief Const value iterator for ET
madcowswe 15:9c5aaeda36dc 46 */
madcowswe 15:9c5aaeda36dc 47 template<class T, std::size_t Sz>
madcowswe 15:9c5aaeda36dc 48 class VectorConstReference
madcowswe 15:9c5aaeda36dc 49 : public TvmetBase< VectorConstReference<T, Sz> >
madcowswe 15:9c5aaeda36dc 50 {
madcowswe 15:9c5aaeda36dc 51 public: // types
madcowswe 15:9c5aaeda36dc 52 typedef T value_type;
madcowswe 15:9c5aaeda36dc 53 typedef T* pointer;
madcowswe 15:9c5aaeda36dc 54 typedef const T* const_pointer;
madcowswe 15:9c5aaeda36dc 55
madcowswe 15:9c5aaeda36dc 56 public:
madcowswe 15:9c5aaeda36dc 57 /** Dimensions. */
madcowswe 15:9c5aaeda36dc 58 enum {
madcowswe 15:9c5aaeda36dc 59 Size = Sz /**< The size of the vector. */
madcowswe 15:9c5aaeda36dc 60 };
madcowswe 15:9c5aaeda36dc 61
madcowswe 15:9c5aaeda36dc 62 public:
madcowswe 15:9c5aaeda36dc 63 /** Complexity counter. */
madcowswe 15:9c5aaeda36dc 64 enum {
madcowswe 15:9c5aaeda36dc 65 ops = Size
madcowswe 15:9c5aaeda36dc 66 };
madcowswe 15:9c5aaeda36dc 67
madcowswe 15:9c5aaeda36dc 68 private:
madcowswe 15:9c5aaeda36dc 69 VectorConstReference();
madcowswe 15:9c5aaeda36dc 70 VectorConstReference& operator=(const VectorConstReference&);
madcowswe 15:9c5aaeda36dc 71
madcowswe 15:9c5aaeda36dc 72 public:
madcowswe 15:9c5aaeda36dc 73 /** Constructor. */
madcowswe 15:9c5aaeda36dc 74 explicit VectorConstReference(const Vector<T, Size>& rhs)
madcowswe 15:9c5aaeda36dc 75 : m_data(rhs.data())
madcowswe 15:9c5aaeda36dc 76 { }
madcowswe 15:9c5aaeda36dc 77
madcowswe 15:9c5aaeda36dc 78 /** Constructor by a given memory pointer. */
madcowswe 15:9c5aaeda36dc 79 explicit VectorConstReference(const_pointer data)
madcowswe 15:9c5aaeda36dc 80 : m_data(data)
madcowswe 15:9c5aaeda36dc 81 { }
madcowswe 15:9c5aaeda36dc 82
madcowswe 15:9c5aaeda36dc 83 public: // access operators
madcowswe 15:9c5aaeda36dc 84 /** access by index. */
madcowswe 15:9c5aaeda36dc 85 value_type operator()(std::size_t i) const {
madcowswe 15:9c5aaeda36dc 86 TVMET_RT_CONDITION(i < Size, "VectorConstReference Bounce Violation")
madcowswe 15:9c5aaeda36dc 87 return m_data[i];
madcowswe 15:9c5aaeda36dc 88 }
madcowswe 15:9c5aaeda36dc 89
madcowswe 15:9c5aaeda36dc 90 public: // debugging Xpr parse tree
madcowswe 15:9c5aaeda36dc 91 void print_xpr(std::ostream& os, std::size_t l=0) const {
madcowswe 15:9c5aaeda36dc 92 os << IndentLevel(l)
madcowswe 15:9c5aaeda36dc 93 << "VectorConstReference[O=" << ops << "]<"
madcowswe 15:9c5aaeda36dc 94 << "T=" << typeid(T).name() << ">,"
madcowswe 15:9c5aaeda36dc 95 << std::endl;
madcowswe 15:9c5aaeda36dc 96 }
madcowswe 15:9c5aaeda36dc 97
madcowswe 15:9c5aaeda36dc 98 private:
madcowswe 15:9c5aaeda36dc 99 const_pointer _tvmet_restrict m_data;
madcowswe 15:9c5aaeda36dc 100 };
madcowswe 15:9c5aaeda36dc 101
madcowswe 15:9c5aaeda36dc 102
madcowswe 15:9c5aaeda36dc 103 /**
madcowswe 15:9c5aaeda36dc 104 * \class Vector Vector.h "tvmet/Vector.h"
madcowswe 15:9c5aaeda36dc 105 * \brief Compile time fixed length vector with evaluation on compile time.
madcowswe 15:9c5aaeda36dc 106 */
madcowswe 15:9c5aaeda36dc 107 template<class T, std::size_t Sz>
madcowswe 15:9c5aaeda36dc 108 class Vector
madcowswe 15:9c5aaeda36dc 109 {
madcowswe 15:9c5aaeda36dc 110 public:
madcowswe 15:9c5aaeda36dc 111 /** Data type of the tvmet::Vector. */
madcowswe 15:9c5aaeda36dc 112 typedef T value_type;
madcowswe 15:9c5aaeda36dc 113
madcowswe 15:9c5aaeda36dc 114 /** Reference type of the tvmet::Vector data elements. */
madcowswe 15:9c5aaeda36dc 115 typedef T& reference;
madcowswe 15:9c5aaeda36dc 116
madcowswe 15:9c5aaeda36dc 117 /** const reference type of the tvmet::Vector data elements. */
madcowswe 15:9c5aaeda36dc 118 typedef const T& const_reference;
madcowswe 15:9c5aaeda36dc 119
madcowswe 15:9c5aaeda36dc 120 /** STL iterator interface. */
madcowswe 15:9c5aaeda36dc 121 typedef T* iterator;
madcowswe 15:9c5aaeda36dc 122
madcowswe 15:9c5aaeda36dc 123 /** STL const_iterator interface. */
madcowswe 15:9c5aaeda36dc 124 typedef const T* const_iterator;
madcowswe 15:9c5aaeda36dc 125
madcowswe 15:9c5aaeda36dc 126 /** STL reverse iterator interface. */
madcowswe 15:9c5aaeda36dc 127 typedef std::reverse_iterator<iterator> reverse_iterator;
madcowswe 15:9c5aaeda36dc 128
madcowswe 15:9c5aaeda36dc 129 /** STL const reverse iterator interface. */
madcowswe 15:9c5aaeda36dc 130 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
madcowswe 15:9c5aaeda36dc 131
madcowswe 15:9c5aaeda36dc 132 public:
madcowswe 15:9c5aaeda36dc 133 /** Dimensions. */
madcowswe 15:9c5aaeda36dc 134 enum {
madcowswe 15:9c5aaeda36dc 135 Size = Sz /**< The size of the vector. */
madcowswe 15:9c5aaeda36dc 136 };
madcowswe 15:9c5aaeda36dc 137
madcowswe 15:9c5aaeda36dc 138 public:
madcowswe 15:9c5aaeda36dc 139 /** Complexity counter. */
madcowswe 15:9c5aaeda36dc 140 enum {
madcowswe 15:9c5aaeda36dc 141 ops_assign = Size,
madcowswe 15:9c5aaeda36dc 142 ops = ops_assign,
madcowswe 15:9c5aaeda36dc 143 use_meta = ops < TVMET_COMPLEXITY_V_ASSIGN_TRIGGER ? true : false
madcowswe 15:9c5aaeda36dc 144 };
madcowswe 15:9c5aaeda36dc 145
madcowswe 15:9c5aaeda36dc 146 public: // STL interface
madcowswe 15:9c5aaeda36dc 147 /** STL iterator interface. */
madcowswe 15:9c5aaeda36dc 148 iterator begin() { return m_data; }
madcowswe 15:9c5aaeda36dc 149
madcowswe 15:9c5aaeda36dc 150 /** STL iterator interface. */
madcowswe 15:9c5aaeda36dc 151 iterator end() { return m_data + Size; }
madcowswe 15:9c5aaeda36dc 152
madcowswe 15:9c5aaeda36dc 153 /** STL const_iterator interface. */
madcowswe 15:9c5aaeda36dc 154 const_iterator begin() const { return m_data; }
madcowswe 15:9c5aaeda36dc 155
madcowswe 15:9c5aaeda36dc 156 /** STL const_iterator interface. */
madcowswe 15:9c5aaeda36dc 157 const_iterator end() const { return m_data + Size; }
madcowswe 15:9c5aaeda36dc 158
madcowswe 15:9c5aaeda36dc 159 /** STL reverse iterator interface reverse begin. */
madcowswe 15:9c5aaeda36dc 160 reverse_iterator rbegin() { return reverse_iterator( end() ); }
madcowswe 15:9c5aaeda36dc 161
madcowswe 15:9c5aaeda36dc 162 /** STL const reverse iterator interface reverse begin. */
madcowswe 15:9c5aaeda36dc 163 const_reverse_iterator rbegin() const {
madcowswe 15:9c5aaeda36dc 164 return const_reverse_iterator( end() );
madcowswe 15:9c5aaeda36dc 165 }
madcowswe 15:9c5aaeda36dc 166
madcowswe 15:9c5aaeda36dc 167 /** STL reverse iterator interface reverse end. */
madcowswe 15:9c5aaeda36dc 168 reverse_iterator rend() { return reverse_iterator( begin() ); }
madcowswe 15:9c5aaeda36dc 169
madcowswe 15:9c5aaeda36dc 170 /** STL const reverse iterator interface reverse end. */
madcowswe 15:9c5aaeda36dc 171 const_reverse_iterator rend() const {
madcowswe 15:9c5aaeda36dc 172 return const_reverse_iterator( begin() );
madcowswe 15:9c5aaeda36dc 173 }
madcowswe 15:9c5aaeda36dc 174
madcowswe 15:9c5aaeda36dc 175 /** STL vector front element. */
madcowswe 15:9c5aaeda36dc 176 value_type front() { return m_data[0]; }
madcowswe 15:9c5aaeda36dc 177
madcowswe 15:9c5aaeda36dc 178 /** STL vector const front element. */
madcowswe 15:9c5aaeda36dc 179 const_reference front() const { return m_data[0]; }
madcowswe 15:9c5aaeda36dc 180
madcowswe 15:9c5aaeda36dc 181 /** STL vector back element. */
madcowswe 15:9c5aaeda36dc 182 value_type back() { return m_data[Size-1]; }
madcowswe 15:9c5aaeda36dc 183
madcowswe 15:9c5aaeda36dc 184 /** STL vector const back element. */
madcowswe 15:9c5aaeda36dc 185 const_reference back() const { return m_data[Size-1]; }
madcowswe 15:9c5aaeda36dc 186
madcowswe 15:9c5aaeda36dc 187 /** STL vector empty() - returns allways false. */
madcowswe 15:9c5aaeda36dc 188 static bool empty() { return false; }
madcowswe 15:9c5aaeda36dc 189
madcowswe 15:9c5aaeda36dc 190 /** The size of the vector. */
madcowswe 15:9c5aaeda36dc 191 static std::size_t size() { return Size; }
madcowswe 15:9c5aaeda36dc 192
madcowswe 15:9c5aaeda36dc 193 /** STL vector max_size() - returns allways Size. */
madcowswe 15:9c5aaeda36dc 194 static std::size_t max_size() { return Size; }
madcowswe 15:9c5aaeda36dc 195
madcowswe 15:9c5aaeda36dc 196 public:
madcowswe 15:9c5aaeda36dc 197 /** Default Destructor */
madcowswe 15:9c5aaeda36dc 198 ~Vector() {
madcowswe 15:9c5aaeda36dc 199 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 200 delete [] m_data;
madcowswe 15:9c5aaeda36dc 201 #endif
madcowswe 15:9c5aaeda36dc 202 }
madcowswe 15:9c5aaeda36dc 203
madcowswe 15:9c5aaeda36dc 204 /** Default Constructor. The allocated memory region isn't cleared. If you want
madcowswe 15:9c5aaeda36dc 205 a clean use the constructor argument zero. */
madcowswe 15:9c5aaeda36dc 206 explicit Vector()
madcowswe 15:9c5aaeda36dc 207 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 208 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 209 #endif
madcowswe 15:9c5aaeda36dc 210 { }
madcowswe 15:9c5aaeda36dc 211
madcowswe 15:9c5aaeda36dc 212 /** Copy Constructor, not explicit! */
madcowswe 15:9c5aaeda36dc 213 Vector(const Vector& rhs)
madcowswe 15:9c5aaeda36dc 214 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 215 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 216 #endif
madcowswe 15:9c5aaeda36dc 217 {
madcowswe 15:9c5aaeda36dc 218 *this = XprVector<ConstReference, Size>(rhs.const_ref());
madcowswe 15:9c5aaeda36dc 219 }
madcowswe 15:9c5aaeda36dc 220
madcowswe 15:9c5aaeda36dc 221 /**
madcowswe 15:9c5aaeda36dc 222 * Constructor with STL iterator interface. The data will be copied into the
madcowswe 15:9c5aaeda36dc 223 * vector self, there isn't any stored reference to the array pointer.
madcowswe 15:9c5aaeda36dc 224 */
madcowswe 15:9c5aaeda36dc 225 template<class InputIterator>
madcowswe 15:9c5aaeda36dc 226 explicit Vector(InputIterator first, InputIterator last)
madcowswe 15:9c5aaeda36dc 227 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 228 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 229 #endif
madcowswe 15:9c5aaeda36dc 230 {
madcowswe 15:9c5aaeda36dc 231 TVMET_RT_CONDITION( static_cast<std::size_t>(std::distance(first, last)) <= Size,
madcowswe 15:9c5aaeda36dc 232 "InputIterator doesn't fits in size" )
madcowswe 15:9c5aaeda36dc 233 std::copy(first, last, m_data);
madcowswe 15:9c5aaeda36dc 234 }
madcowswe 15:9c5aaeda36dc 235
madcowswe 15:9c5aaeda36dc 236 /**
madcowswe 15:9c5aaeda36dc 237 * Constructor with STL iterator interface. The data will be copied into the
madcowswe 15:9c5aaeda36dc 238 * vector self, there isn't any stored reference to the array pointer.
madcowswe 15:9c5aaeda36dc 239 */
madcowswe 15:9c5aaeda36dc 240 template<class InputIterator>
madcowswe 15:9c5aaeda36dc 241 explicit Vector(InputIterator first, std::size_t sz)
madcowswe 15:9c5aaeda36dc 242 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 243 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 244 #endif
madcowswe 15:9c5aaeda36dc 245 {
madcowswe 15:9c5aaeda36dc 246 TVMET_RT_CONDITION( sz <= Size, "InputIterator doesn't fits in size" )
madcowswe 15:9c5aaeda36dc 247 std::copy(first, first + sz, m_data);
madcowswe 15:9c5aaeda36dc 248 }
madcowswe 15:9c5aaeda36dc 249
madcowswe 15:9c5aaeda36dc 250 /** Constructor with initializer for all elements. */
madcowswe 15:9c5aaeda36dc 251 explicit Vector(value_type rhs)
madcowswe 15:9c5aaeda36dc 252 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 253 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 254 #endif
madcowswe 15:9c5aaeda36dc 255 {
madcowswe 15:9c5aaeda36dc 256 typedef XprLiteral<value_type> expr_type;
madcowswe 15:9c5aaeda36dc 257 *this = XprVector<expr_type, Size>(expr_type(rhs));
madcowswe 15:9c5aaeda36dc 258 }
madcowswe 15:9c5aaeda36dc 259
madcowswe 15:9c5aaeda36dc 260 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 261 explicit Vector(value_type x0, value_type x1)
madcowswe 15:9c5aaeda36dc 262 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 263 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 264 #endif
madcowswe 15:9c5aaeda36dc 265 {
madcowswe 15:9c5aaeda36dc 266 TVMET_CT_CONDITION(2 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 267 m_data[0] = x0; m_data[1] = x1;
madcowswe 15:9c5aaeda36dc 268 }
madcowswe 15:9c5aaeda36dc 269
madcowswe 15:9c5aaeda36dc 270 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 271 explicit Vector(value_type x0, value_type x1, value_type x2)
madcowswe 15:9c5aaeda36dc 272 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 273 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 274 #endif
madcowswe 15:9c5aaeda36dc 275 {
madcowswe 15:9c5aaeda36dc 276 TVMET_CT_CONDITION(3 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 277 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2;
madcowswe 15:9c5aaeda36dc 278 }
madcowswe 15:9c5aaeda36dc 279
madcowswe 15:9c5aaeda36dc 280 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 281 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3)
madcowswe 15:9c5aaeda36dc 282 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 283 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 284 #endif
madcowswe 15:9c5aaeda36dc 285 {
madcowswe 15:9c5aaeda36dc 286 TVMET_CT_CONDITION(4 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 287 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3;
madcowswe 15:9c5aaeda36dc 288 }
madcowswe 15:9c5aaeda36dc 289
madcowswe 15:9c5aaeda36dc 290 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 291 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 292 value_type x4)
madcowswe 15:9c5aaeda36dc 293 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 294 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 295 #endif
madcowswe 15:9c5aaeda36dc 296 {
madcowswe 15:9c5aaeda36dc 297 TVMET_CT_CONDITION(5 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 298 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 299 }
madcowswe 15:9c5aaeda36dc 300
madcowswe 15:9c5aaeda36dc 301 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 302 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 303 value_type x4, value_type x5)
madcowswe 15:9c5aaeda36dc 304 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 305 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 306 #endif
madcowswe 15:9c5aaeda36dc 307 {
madcowswe 15:9c5aaeda36dc 308 TVMET_CT_CONDITION(6 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 309 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 310 m_data[5] = x5;
madcowswe 15:9c5aaeda36dc 311 }
madcowswe 15:9c5aaeda36dc 312
madcowswe 15:9c5aaeda36dc 313 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 314 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 315 value_type x4, value_type x5, value_type x6)
madcowswe 15:9c5aaeda36dc 316 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 317 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 318 #endif
madcowswe 15:9c5aaeda36dc 319 {
madcowswe 15:9c5aaeda36dc 320 TVMET_CT_CONDITION(7 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 321 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 322 m_data[5] = x5; m_data[6] = x6;
madcowswe 15:9c5aaeda36dc 323 }
madcowswe 15:9c5aaeda36dc 324
madcowswe 15:9c5aaeda36dc 325 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 326 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 327 value_type x4, value_type x5, value_type x6, value_type x7)
madcowswe 15:9c5aaeda36dc 328 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 329 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 330 #endif
madcowswe 15:9c5aaeda36dc 331 {
madcowswe 15:9c5aaeda36dc 332 TVMET_CT_CONDITION(8 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 333 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 334 m_data[5] = x5; m_data[6] = x6; m_data[7] = x7;
madcowswe 15:9c5aaeda36dc 335 }
madcowswe 15:9c5aaeda36dc 336
madcowswe 15:9c5aaeda36dc 337 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 338 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 339 value_type x4, value_type x5, value_type x6, value_type x7,
madcowswe 15:9c5aaeda36dc 340 value_type x8)
madcowswe 15:9c5aaeda36dc 341 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 342 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 343 #endif
madcowswe 15:9c5aaeda36dc 344 {
madcowswe 15:9c5aaeda36dc 345 TVMET_CT_CONDITION(9 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 346 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 347 m_data[5] = x5; m_data[6] = x6; m_data[7] = x7; m_data[8] = x8;
madcowswe 15:9c5aaeda36dc 348 }
madcowswe 15:9c5aaeda36dc 349
madcowswe 15:9c5aaeda36dc 350 /** Default Constructor with initializer list. */
madcowswe 15:9c5aaeda36dc 351 explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
madcowswe 15:9c5aaeda36dc 352 value_type x4, value_type x5, value_type x6, value_type x7,
madcowswe 15:9c5aaeda36dc 353 value_type x8, value_type x9)
madcowswe 15:9c5aaeda36dc 354 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 355 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 356 #endif
madcowswe 15:9c5aaeda36dc 357 {
madcowswe 15:9c5aaeda36dc 358 TVMET_CT_CONDITION(10 <= Size, ArgumentList_is_too_long)
madcowswe 15:9c5aaeda36dc 359 m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
madcowswe 15:9c5aaeda36dc 360 m_data[5] = x5; m_data[6] = x6; m_data[7] = x7; m_data[8] = x8; m_data[9] = x9;
madcowswe 15:9c5aaeda36dc 361 }
madcowswe 15:9c5aaeda36dc 362
madcowswe 15:9c5aaeda36dc 363 /** Construct a vector by expression. */
madcowswe 15:9c5aaeda36dc 364 template <class E>
madcowswe 15:9c5aaeda36dc 365 explicit Vector(const XprVector<E, Size>& e)
madcowswe 15:9c5aaeda36dc 366 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 367 : m_data( new value_type[Size] )
madcowswe 15:9c5aaeda36dc 368 #endif
madcowswe 15:9c5aaeda36dc 369 {
madcowswe 15:9c5aaeda36dc 370 *this = e;
madcowswe 15:9c5aaeda36dc 371 }
madcowswe 15:9c5aaeda36dc 372
madcowswe 15:9c5aaeda36dc 373 /** Assign a value_type on array, this can be used for a single value
madcowswe 15:9c5aaeda36dc 374 or a comma separeted list of values. */
madcowswe 15:9c5aaeda36dc 375 CommaInitializer<Vector, Size> operator=(value_type rhs) {
madcowswe 15:9c5aaeda36dc 376 return CommaInitializer<Vector, Size>(*this, rhs);
madcowswe 15:9c5aaeda36dc 377 }
madcowswe 15:9c5aaeda36dc 378
madcowswe 15:9c5aaeda36dc 379 public: // access operators
madcowswe 15:9c5aaeda36dc 380 value_type* _tvmet_restrict data() { return m_data; }
madcowswe 15:9c5aaeda36dc 381 const value_type* _tvmet_restrict data() const { return m_data; }
madcowswe 15:9c5aaeda36dc 382
madcowswe 15:9c5aaeda36dc 383 public: // index access operators
madcowswe 15:9c5aaeda36dc 384 value_type& _tvmet_restrict operator()(std::size_t i) {
madcowswe 15:9c5aaeda36dc 385 // Note: g++-2.95.3 does have problems on typedef reference
madcowswe 15:9c5aaeda36dc 386 TVMET_RT_CONDITION(i < Size, "Vector Bounce Violation")
madcowswe 15:9c5aaeda36dc 387 return m_data[i];
madcowswe 15:9c5aaeda36dc 388 }
madcowswe 15:9c5aaeda36dc 389
madcowswe 15:9c5aaeda36dc 390 value_type operator()(std::size_t i) const {
madcowswe 15:9c5aaeda36dc 391 TVMET_RT_CONDITION(i < Size, "Vector Bounce Violation")
madcowswe 15:9c5aaeda36dc 392 return m_data[i];
madcowswe 15:9c5aaeda36dc 393 }
madcowswe 15:9c5aaeda36dc 394
madcowswe 15:9c5aaeda36dc 395 value_type& _tvmet_restrict operator[](std::size_t i) {
madcowswe 15:9c5aaeda36dc 396 // Note: g++-2.95.3 does have problems on typedef reference
madcowswe 15:9c5aaeda36dc 397 return this->operator()(i);
madcowswe 15:9c5aaeda36dc 398 }
madcowswe 15:9c5aaeda36dc 399
madcowswe 15:9c5aaeda36dc 400 value_type operator[](std::size_t i) const {
madcowswe 15:9c5aaeda36dc 401 return this->operator()(i);
madcowswe 15:9c5aaeda36dc 402 }
madcowswe 15:9c5aaeda36dc 403
madcowswe 15:9c5aaeda36dc 404 public: // ET interface
madcowswe 15:9c5aaeda36dc 405 typedef VectorConstReference<T, Size> ConstReference;
madcowswe 15:9c5aaeda36dc 406
madcowswe 15:9c5aaeda36dc 407 /** Return a const Reference of the internal data */
madcowswe 15:9c5aaeda36dc 408 ConstReference const_ref() const { return ConstReference(*this); }
madcowswe 15:9c5aaeda36dc 409
madcowswe 15:9c5aaeda36dc 410 /** Return the vector as const expression. */
madcowswe 15:9c5aaeda36dc 411 XprVector<ConstReference, Size> as_expr() const {
madcowswe 15:9c5aaeda36dc 412 return XprVector<ConstReference, Size>(this->const_ref());
madcowswe 15:9c5aaeda36dc 413 }
madcowswe 15:9c5aaeda36dc 414
madcowswe 15:9c5aaeda36dc 415 private:
madcowswe 15:9c5aaeda36dc 416 /** Wrapper for meta assign. */
madcowswe 15:9c5aaeda36dc 417 template<class Dest, class Src, class Assign>
madcowswe 15:9c5aaeda36dc 418 static inline
madcowswe 15:9c5aaeda36dc 419 void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
madcowswe 15:9c5aaeda36dc 420 meta::Vector<Size, 0>::assign(dest, src, assign_fn);
madcowswe 15:9c5aaeda36dc 421 }
madcowswe 15:9c5aaeda36dc 422
madcowswe 15:9c5aaeda36dc 423 /** Wrapper for loop assign. */
madcowswe 15:9c5aaeda36dc 424 template<class Dest, class Src, class Assign>
madcowswe 15:9c5aaeda36dc 425 static inline
madcowswe 15:9c5aaeda36dc 426 void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
madcowswe 15:9c5aaeda36dc 427 loop::Vector<Size>::assign(dest, src, assign_fn);
madcowswe 15:9c5aaeda36dc 428 }
madcowswe 15:9c5aaeda36dc 429
madcowswe 15:9c5aaeda36dc 430 public:
madcowswe 15:9c5aaeda36dc 431 /** assign this to a vector expression using the functional assign_fn. */
madcowswe 15:9c5aaeda36dc 432 template<class T2, class Assign>
madcowswe 15:9c5aaeda36dc 433 void assign_to(Vector<T2, Size>& dest, const Assign& assign_fn) const {
madcowswe 15:9c5aaeda36dc 434 do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
madcowswe 15:9c5aaeda36dc 435 }
madcowswe 15:9c5aaeda36dc 436
madcowswe 15:9c5aaeda36dc 437 public: // assign operations
madcowswe 15:9c5aaeda36dc 438 /** assign a given Vector element wise to this vector.
madcowswe 15:9c5aaeda36dc 439 The operator=(const Vector&) is compiler generated. */
madcowswe 15:9c5aaeda36dc 440 template<class T2>
madcowswe 15:9c5aaeda36dc 441 Vector& operator=(const Vector<T2, Size>& rhs) {
madcowswe 15:9c5aaeda36dc 442 rhs.assign_to(*this, Fcnl_assign<value_type, T2>());
madcowswe 15:9c5aaeda36dc 443 return *this;
madcowswe 15:9c5aaeda36dc 444 }
madcowswe 15:9c5aaeda36dc 445
madcowswe 15:9c5aaeda36dc 446 /** assign a given XprVector element wise to this vector. */
madcowswe 15:9c5aaeda36dc 447 template<class E>
madcowswe 15:9c5aaeda36dc 448 Vector& operator=(const XprVector<E, Size>& rhs) {
madcowswe 15:9c5aaeda36dc 449 rhs.assign_to(*this, Fcnl_assign<value_type, typename E::value_type>());
madcowswe 15:9c5aaeda36dc 450 return *this;
madcowswe 15:9c5aaeda36dc 451 }
madcowswe 15:9c5aaeda36dc 452
madcowswe 15:9c5aaeda36dc 453 private:
madcowswe 15:9c5aaeda36dc 454 template<class Obj, std::size_t LEN> friend class CommaInitializer;
madcowswe 15:9c5aaeda36dc 455
madcowswe 15:9c5aaeda36dc 456 /** This is a helper for assigning a comma separated initializer
madcowswe 15:9c5aaeda36dc 457 list. It's equal to Vector& operator=(value_type) which does
madcowswe 15:9c5aaeda36dc 458 replace it. */
madcowswe 15:9c5aaeda36dc 459 Vector& assign_value(value_type rhs) {
madcowswe 15:9c5aaeda36dc 460 typedef XprLiteral<value_type> expr_type;
madcowswe 15:9c5aaeda36dc 461 *this = XprVector<expr_type, Size>(expr_type(rhs));
madcowswe 15:9c5aaeda36dc 462 return *this;
madcowswe 15:9c5aaeda36dc 463 }
madcowswe 15:9c5aaeda36dc 464
madcowswe 15:9c5aaeda36dc 465 public: // math operators with scalars
madcowswe 15:9c5aaeda36dc 466 // NOTE: this meaning is clear - element wise ops even if not in ns element_wise
madcowswe 15:9c5aaeda36dc 467 Vector& operator+=(value_type) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 468 Vector& operator-=(value_type) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 469 Vector& operator*=(value_type) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 470 Vector& operator/=(value_type) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 471
madcowswe 15:9c5aaeda36dc 472 Vector& operator%=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 473 Vector& operator^=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 474 Vector& operator&=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 475 Vector& operator|=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 476 Vector& operator<<=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 477 Vector& operator>>=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 478
madcowswe 15:9c5aaeda36dc 479 public: // math assign operators with vectors
madcowswe 15:9c5aaeda36dc 480 // NOTE: access using the operators in ns element_wise, since that's what is does
madcowswe 15:9c5aaeda36dc 481 template <class T2> Vector& M_add_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 482 template <class T2> Vector& M_sub_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 483 template <class T2> Vector& M_mul_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 484 template <class T2> Vector& M_div_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 485 template <class T2> Vector& M_mod_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 486 template <class T2> Vector& M_xor_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 487 template <class T2> Vector& M_and_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 488 template <class T2> Vector& M_or_eq (const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 489 template <class T2> Vector& M_shl_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 490 template <class T2> Vector& M_shr_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 491
madcowswe 15:9c5aaeda36dc 492 public: // math operators with expressions
madcowswe 15:9c5aaeda36dc 493 // NOTE: access using the operators in ns element_wise, since that's what is does
madcowswe 15:9c5aaeda36dc 494 template <class E> Vector& M_add_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 495 template <class E> Vector& M_sub_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 496 template <class E> Vector& M_mul_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 497 template <class E> Vector& M_div_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 498 template <class E> Vector& M_mod_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 499 template <class E> Vector& M_xor_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 500 template <class E> Vector& M_and_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 501 template <class E> Vector& M_or_eq (const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 502 template <class E> Vector& M_shl_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 503 template <class E> Vector& M_shr_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 504
madcowswe 15:9c5aaeda36dc 505 public: // aliased math operators with expressions, used with proxy
madcowswe 15:9c5aaeda36dc 506 template <class T2> Vector& alias_assign(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 507 template <class T2> Vector& alias_add_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 508 template <class T2> Vector& alias_sub_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 509 template <class T2> Vector& alias_mul_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 510 template <class T2> Vector& alias_div_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 511
madcowswe 15:9c5aaeda36dc 512 template <class E> Vector& alias_assign(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 513 template <class E> Vector& alias_add_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 514 template <class E> Vector& alias_sub_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 515 template <class E> Vector& alias_mul_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 516 template <class E> Vector& alias_div_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
madcowswe 15:9c5aaeda36dc 517
madcowswe 15:9c5aaeda36dc 518 public: // io
madcowswe 15:9c5aaeda36dc 519 /** Structure for info printing as Vector<T, Size>. */
madcowswe 15:9c5aaeda36dc 520 struct Info : public TvmetBase<Info> {
madcowswe 15:9c5aaeda36dc 521 std::ostream& print_xpr(std::ostream& os) const {
madcowswe 15:9c5aaeda36dc 522 os << "Vector<T=" << typeid(value_type).name()
madcowswe 15:9c5aaeda36dc 523 << ", Sz=" << Size << ">";
madcowswe 15:9c5aaeda36dc 524 return os;
madcowswe 15:9c5aaeda36dc 525 }
madcowswe 15:9c5aaeda36dc 526 };
madcowswe 15:9c5aaeda36dc 527
madcowswe 15:9c5aaeda36dc 528 /** Get an info object of this vector. */
madcowswe 15:9c5aaeda36dc 529 static Info info() { return Info(); }
madcowswe 15:9c5aaeda36dc 530
madcowswe 15:9c5aaeda36dc 531 /** Member function for expression level printing. */
madcowswe 15:9c5aaeda36dc 532 std::ostream& print_xpr(std::ostream& os, std::size_t l=0) const;
madcowswe 15:9c5aaeda36dc 533
madcowswe 15:9c5aaeda36dc 534 /** Member function for printing internal data. */
madcowswe 15:9c5aaeda36dc 535 std::ostream& print_on(std::ostream& os) const;
madcowswe 15:9c5aaeda36dc 536
madcowswe 15:9c5aaeda36dc 537 private:
madcowswe 15:9c5aaeda36dc 538 /** The data of vector self. */
madcowswe 15:9c5aaeda36dc 539
madcowswe 15:9c5aaeda36dc 540 #if defined(TVMET_DYNAMIC_MEMORY)
madcowswe 15:9c5aaeda36dc 541 value_type* m_data;
madcowswe 15:9c5aaeda36dc 542 #else
madcowswe 15:9c5aaeda36dc 543 value_type m_data[Size];
madcowswe 15:9c5aaeda36dc 544 #endif
madcowswe 15:9c5aaeda36dc 545 };
madcowswe 15:9c5aaeda36dc 546
madcowswe 15:9c5aaeda36dc 547
madcowswe 15:9c5aaeda36dc 548 } // namespace tvmet
madcowswe 15:9c5aaeda36dc 549
madcowswe 15:9c5aaeda36dc 550 #include <tvmet/VectorImpl.h>
madcowswe 15:9c5aaeda36dc 551 #include <tvmet/VectorFunctions.h>
madcowswe 15:9c5aaeda36dc 552 #include <tvmet/VectorBinaryFunctions.h>
madcowswe 15:9c5aaeda36dc 553 #include <tvmet/VectorUnaryFunctions.h>
madcowswe 15:9c5aaeda36dc 554 #include <tvmet/VectorOperators.h>
madcowswe 15:9c5aaeda36dc 555 #include <tvmet/VectorEval.h>
madcowswe 15:9c5aaeda36dc 556 #include <tvmet/AliasProxy.h>
madcowswe 15:9c5aaeda36dc 557
madcowswe 15:9c5aaeda36dc 558 #endif // TVMET_VECTOR_H
madcowswe 15:9c5aaeda36dc 559
madcowswe 15:9c5aaeda36dc 560 // Local Variables:
madcowswe 15:9c5aaeda36dc 561 // mode:C++
madcowswe 15:9c5aaeda36dc 562 // tab-width:8
madcowswe 15:9c5aaeda36dc 563 // End: