]> git.tdb.fi Git - libs/math.git/blob - source/linal/dynamicvector.h
Add formatted output operators for vector and matrix classes
[libs/math.git] / source / linal / dynamicvector.h
1 #ifndef MSP_LINAL_DYNAMICVECTOR_H_
2 #define MSP_LINAL_DYNAMICVECTOR_H_
3
4 #include <algorithm>
5 #include <cmath>
6 #include <ostream>
7 #include <stdexcept>
8
9 namespace Msp {
10 namespace LinAl {
11
12 class size_mismatch: public std::logic_error
13 {
14 public:
15         size_mismatch(const std::string &w): std::logic_error(w) { }
16         virtual ~size_mismatch() throw() { }
17 };
18
19
20 /**
21 A general mathematical vector.  Size is specified at runtime.  May be slower
22 than a fixed-size vector.  There are no compile-time diagnostics for mismatched
23 vector sizes.
24 */
25 template<typename T>
26 class DynamicVector
27 {
28 public:
29         typedef T ElementType;
30
31 private:
32         unsigned size_;
33         T *data;
34
35 public:
36         DynamicVector(unsigned);
37         DynamicVector(unsigned, const T *);
38         DynamicVector(const DynamicVector &);
39         DynamicVector &operator=(const DynamicVector &);
40         ~DynamicVector();
41
42         unsigned size() const { return size_; }
43
44         T &operator[](unsigned);
45         const T &operator[](unsigned) const;
46
47         DynamicVector &operator*=(T);
48         DynamicVector &operator/=(T);
49         DynamicVector &operator+=(const DynamicVector &);
50         DynamicVector &operator-=(const DynamicVector &);
51
52         T norm() const;
53         DynamicVector &normalize();
54 };
55
56 template<typename T>
57 inline DynamicVector<T>::DynamicVector(unsigned s):
58         size_(s),
59         data(new T[size_])
60 {
61         std::fill(data, data+size_, T());
62 }
63
64 template<typename T>
65 inline DynamicVector<T>::DynamicVector(unsigned s, const T *d):
66         size_(s),
67         data(new T[size_])
68 {
69         std::copy(d, d+size_, data);
70 }
71
72 template<typename T>
73 inline DynamicVector<T>::DynamicVector(const DynamicVector &other):
74         size_(other.size()),
75         data(new T[size_])
76 {
77         std::copy(other.data, other.data+size_, data);
78 }
79
80 template<typename T>
81 inline DynamicVector<T> &DynamicVector<T>::operator=(const DynamicVector<T> &other)
82 {
83         if(size_!=other.size())
84         {
85                 delete[] data;
86                 size_ = other.size();
87                 data = new T[size_];
88         }
89
90         std::copy(other.data, other.data+size_, data);
91
92         return *this;
93 }
94
95 template<typename T>
96 inline DynamicVector<T>::~DynamicVector()
97 {
98         delete[] data;
99 }
100
101 template<typename T>
102 inline T &DynamicVector<T>::operator[](unsigned i)
103 {
104         if(i>=size_)
105                 throw std::out_of_range("DynamicVector::operator[]");
106
107         return data[i];
108 }
109
110 template<typename T>
111 inline const T &DynamicVector<T>::operator[](unsigned i) const
112 {
113         if(i>=size_)
114                 throw std::out_of_range("DynamicVector::operator[]");
115
116         return data[i];
117 }
118
119 template<typename T>
120 inline DynamicVector<T> &DynamicVector<T>::operator*=(T s)
121 {
122         for(unsigned i=0; i<size_; ++i)
123                 data[i] *= s;
124         return *this;
125 }
126
127 template<typename T>
128 inline DynamicVector<T> operator*(const DynamicVector<T> &v, T s)
129 {
130         DynamicVector<T> r(v);
131         return r *= s;
132 }
133
134 template<typename T>
135 inline DynamicVector<T> operator*(T s, const DynamicVector<T> &v)
136 {
137         return v*s;
138 }
139
140 template<typename T>
141 inline DynamicVector<T> &DynamicVector<T>::operator/=(T s)
142 {
143         for(unsigned i=0; i<size_; ++i)
144                 data[i] /= s;
145         return *this;
146 }
147
148 template<typename T>
149 inline DynamicVector<T> operator/(const DynamicVector<T> &v, T s)
150 {
151         DynamicVector<T> r(v);
152         return r /= s;
153 }
154
155 template<typename T>
156 inline DynamicVector<T> &DynamicVector<T>::operator+=(const DynamicVector<T> &v)
157 {
158         if(size_!=v.size())
159                 throw size_mismatch("vector+vector");
160
161         for(unsigned i=0; i<size_; ++i)
162                 data[i] += v.data[i];
163
164         return *this;
165 }
166
167 template<typename T>
168 inline DynamicVector<T> operator+(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
169 {
170         DynamicVector<T> r(v1);
171         return r += v2;
172 }
173
174 template<typename T>
175 inline DynamicVector<T> &DynamicVector<T>::operator-=(const DynamicVector<T> &v)
176 {
177         if(size_!=v.size())
178                 throw size_mismatch("vector-vector");
179
180         for(unsigned i=0; i<size_; ++i)
181                 data[i] -= v.data[i];
182
183         return *this;
184 }
185
186 template<typename T>
187 inline DynamicVector<T> operator-(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
188 {
189         DynamicVector<T> r(v1);
190         return r -= v2;
191 }
192
193 template<typename T>
194 inline DynamicVector<T> operator-(const DynamicVector<T> &v)
195 {
196         DynamicVector<T> r(v);
197         for(unsigned i=0; i<r.size(); ++i)
198                 r[i] = -r[i];
199         return r;
200 }
201
202 template<typename T>
203 inline bool operator==(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
204 {
205         if(v1.size()!=v2.size())
206                 throw size_mismatch("vector==vector");
207
208         for(unsigned i=0; i<v1.size(); ++i)
209                 if(v1[i]!=v2[i])
210                         return false;
211
212         return true;
213 }
214
215 template<typename T>
216 inline T inner_product(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
217 {
218         if(v1.size()!=v2.size())
219                 throw size_mismatch("inner_product");
220
221         T r = T();
222         for(unsigned i=0; i<v1.size(); ++i)
223                 r += v1[i]*v2[i];
224         return r;
225 }
226
227 template<typename T>
228 inline T DynamicVector<T>::norm() const
229 {
230         using std::sqrt;
231         return sqrt(inner_product(*this, *this));
232 }
233
234 template<typename T>
235 inline DynamicVector<T> &DynamicVector<T>::normalize()
236 {
237         return *this /= norm();
238 }
239
240 template<typename T>
241 inline DynamicVector<T> normalize(const DynamicVector<T> &v)
242 {
243         DynamicVector<T> r(v);
244         return r.normalize();
245 }
246
247 template<typename T>
248 inline std::ostream &operator<<(std::ostream &s, const DynamicVector<T> &v)
249 {
250         s << "DynamicVector" << v.size() << '(';
251         for(unsigned i=0; i<v.size(); ++i)
252         {
253                 if(i)
254                         s << ", ";
255                 s << v[i];
256         }
257         s << ')';
258         return s;
259 }
260
261 } // namespace LinAL
262 } // namespace Msp
263
264 #endif