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