]> git.tdb.fi Git - libs/math.git/blobdiff - source/linal/dynamicvector.h
Add dynamically allocated versions of matrix and vector
[libs/math.git] / source / linal / dynamicvector.h
diff --git a/source/linal/dynamicvector.h b/source/linal/dynamicvector.h
new file mode 100644 (file)
index 0000000..8839c33
--- /dev/null
@@ -0,0 +1,249 @@
+#ifndef MSP_LINAL_DYNAMICVECTOR_H_
+#define MSP_LINAL_DYNAMICVECTOR_H_
+
+#include <algorithm>
+#include <cmath>
+#include <stdexcept>
+
+namespace Msp {
+namespace LinAl {
+
+class size_mismatch: public std::logic_error
+{
+public:
+       size_mismatch(const std::string &w): std::logic_error(w) { }
+       virtual ~size_mismatch() throw() { }
+};
+
+
+/**
+A general mathematical vector.  Size is specified at runtime.  May be slower
+than a fixed-size vector.  There are no compile-time diagnostics for mismatched
+vector sizes.
+*/
+template<typename T>
+class DynamicVector
+{
+public:
+       typedef T ElementType;
+
+private:
+       unsigned size_;
+       T *data;
+
+public:
+       DynamicVector(unsigned);
+       DynamicVector(unsigned, const T *);
+       DynamicVector(const DynamicVector &);
+       DynamicVector &operator=(const DynamicVector &);
+       ~DynamicVector();
+
+       unsigned size() const { return size_; }
+
+       T &operator[](unsigned);
+       const T &operator[](unsigned) const;
+
+       DynamicVector &operator*=(T);
+       DynamicVector &operator/=(T);
+       DynamicVector &operator+=(const DynamicVector &);
+       DynamicVector &operator-=(const DynamicVector &);
+
+       T norm() const;
+       DynamicVector &normalize();
+};
+
+template<typename T>
+inline DynamicVector<T>::DynamicVector(unsigned s):
+       size_(s),
+       data(new T[size_])
+{
+       std::fill(data, data+size_, T());
+}
+
+template<typename T>
+inline DynamicVector<T>::DynamicVector(unsigned s, const T *d):
+       size_(s),
+       data(new T[size_])
+{
+       std::copy(d, d+size_, data);
+}
+
+template<typename T>
+inline DynamicVector<T>::DynamicVector(const DynamicVector &other):
+       size_(other.size()),
+       data(new T[size_])
+{
+       std::copy(other.data, other.data+size_, data);
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::operator=(const DynamicVector<T> &other)
+{
+       if(size_!=other.size())
+       {
+               delete[] data;
+               size_ = other.size();
+               data = new T[size_];
+       }
+
+       std::copy(other.data, other.data+size_, data);
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicVector<T>::~DynamicVector()
+{
+       delete[] data;
+}
+
+template<typename T>
+inline T &DynamicVector<T>::operator[](unsigned i)
+{
+       if(i>=size_)
+               throw std::out_of_range("DynamicVector::operator[]");
+
+       return data[i];
+}
+
+template<typename T>
+inline const T &DynamicVector<T>::operator[](unsigned i) const
+{
+       if(i>=size_)
+               throw std::out_of_range("DynamicVector::operator[]");
+
+       return data[i];
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::operator*=(T s)
+{
+       for(unsigned i=0; i<size_; ++i)
+               data[i] *= s;
+       return *this;
+}
+
+template<typename T>
+inline DynamicVector<T> operator*(const DynamicVector<T> &v, T s)
+{
+       DynamicVector<T> r(v);
+       return r *= s;
+}
+
+template<typename T>
+inline DynamicVector<T> operator*(T s, const DynamicVector<T> &v)
+{
+       return v*s;
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::operator/=(T s)
+{
+       for(unsigned i=0; i<size_; ++i)
+               data[i] /= s;
+       return *this;
+}
+
+template<typename T>
+inline DynamicVector<T> operator/(const DynamicVector<T> &v, T s)
+{
+       DynamicVector<T> r(v);
+       return r /= s;
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::operator+=(const DynamicVector<T> &v)
+{
+       if(size_!=v.size())
+               throw size_mismatch("vector+vector");
+
+       for(unsigned i=0; i<size_; ++i)
+               data[i] += v.data[i];
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicVector<T> operator+(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
+{
+       DynamicVector<T> r(v1);
+       return r += v2;
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::operator-=(const DynamicVector<T> &v)
+{
+       if(size_!=v.size())
+               throw size_mismatch("vector-vector");
+
+       for(unsigned i=0; i<size_; ++i)
+               data[i] -= v.data[i];
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicVector<T> operator-(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
+{
+       DynamicVector<T> r(v1);
+       return r -= v2;
+}
+
+template<typename T>
+inline DynamicVector<T> operator-(const DynamicVector<T> &v)
+{
+       DynamicVector<T> r(v);
+       for(unsigned i=0; i<r.size(); ++i)
+               r[i] = -r[i];
+       return r;
+}
+
+template<typename T>
+inline bool operator==(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
+{
+       if(v1.size()!=v2.size())
+               throw size_mismatch("vector==vector");
+
+       for(unsigned i=0; i<v1.size(); ++i)
+               if(v1[i]!=v2[i])
+                       return false;
+
+       return true;
+}
+
+template<typename T>
+inline T inner_product(const DynamicVector<T> &v1, const DynamicVector<T> &v2)
+{
+       if(v1.size()!=v2.size())
+               throw size_mismatch("inner_product");
+
+       T r = T();
+       for(unsigned i=0; i<v1.size(); ++i)
+               r += v1[i]*v2[i];
+       return r;
+}
+
+template<typename T>
+inline T DynamicVector<T>::norm() const
+{
+       using std::sqrt;
+       return sqrt(inner_product(*this, *this));
+}
+
+template<typename T>
+inline DynamicVector<T> &DynamicVector<T>::normalize()
+{
+       return *this /= norm();
+}
+
+template<typename T>
+inline DynamicVector<T> normalize(const DynamicVector<T> &v)
+{
+       DynamicVector<T> r(v);
+       return r.normalize();
+}
+
+} // namespace LinAL
+} // namespace Msp
+
+#endif