You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
11 KiB
382 lines
11 KiB
/* |
|
* Vector.h |
|
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> |
|
* |
|
* This file is free software: you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License as published by the |
|
* Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This file is distributed in the hope that it will be useful, but |
|
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
* See the GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License along |
|
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
#ifndef Vector_H |
|
#define Vector_H |
|
|
|
#include "../FastSerial/BetterStream.h" |
|
#include <stdlib.h> |
|
#include <inttypes.h> |
|
#if defined(ARDUINO) && ARDUINO >= 100 |
|
#include "Arduino.h" |
|
#else |
|
#include <WProgram.h> |
|
#endif |
|
|
|
#ifdef ASSERT |
|
const static char vectorSource[] ="Vector.hpp"; |
|
#endif |
|
|
|
// vector |
|
template <class dataType,class sumType=dataType> |
|
class Vector |
|
{ |
|
private: |
|
size_t size; |
|
size_t extraAllocationSize; // extra space to add after each allocation |
|
size_t sizeAllocated; // total allocated size |
|
dataType* data; |
|
public: |
|
// default constructor |
|
Vector(const size_t & _size=0, const size_t & _extraAllocationSize=0) : size(0), extraAllocationSize(_extraAllocationSize), sizeAllocated(0), data(NULL) { |
|
setSize(_size); |
|
} |
|
// 3 vector constructor |
|
Vector(const dataType & a, const dataType & b, const dataType & c) : size(3), extraAllocationSize(extraAllocationSize), sizeAllocated(0), data(NULL) { |
|
setSize(size); |
|
(*this)[0]=a; |
|
(*this)[1]=b; |
|
(*this)[2]=c; |
|
} |
|
|
|
// construct from array |
|
Vector(const dataType* array, const size_t & _size, const size_t & _extraAllocationSize=0) : size(0), extraAllocationSize(_extraAllocationSize), sizeAllocated(0), data(NULL) { |
|
setSize(_size); |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)[i]=array[i]; |
|
} |
|
// copy constructor |
|
Vector(const Vector &v) : size(0), extraAllocationSize(0), sizeAllocated(0), data(NULL) { |
|
setSize(v.getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)[i]=v[i]; |
|
} |
|
// convert to float vector |
|
Vector<float> toFloat() const { |
|
Vector<float> v(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
v[i]=(*this)[i]; |
|
return v; |
|
} |
|
// destructor |
|
virtual ~Vector() { |
|
empty(); |
|
} |
|
void empty() { |
|
if (data) delete [] data; |
|
data = NULL; |
|
sizeAllocated=0; |
|
size=0; |
|
} |
|
// set the size |
|
void setSize(const size_t & n) { |
|
if (n==0) { |
|
if (data) delete [] data; |
|
data = NULL; |
|
sizeAllocated=0; |
|
} |
|
if (n>sizeAllocated) { |
|
dataType * newData = new dataType[n+extraAllocationSize]; |
|
memcpy(newData,data,sizeof(dataType)/sizeof(char)*getSize()); |
|
memset(newData+size,0,sizeof(dataType)/sizeof(char)*(n-getSize())); |
|
delete[] data; |
|
data = newData; |
|
sizeAllocated=n+extraAllocationSize; |
|
} |
|
size=n; |
|
} |
|
// return size |
|
const size_t & getSize() const { |
|
return size; |
|
} |
|
// insert |
|
void insert(const size_t index, const dataType value) { |
|
//Serial.println("insert called"); |
|
#ifdef ASSERT |
|
assert(index<size+1,vectorSource,__LINE__); |
|
#endif |
|
//Serial.print("Old Size: "); |
|
//Serial.println(getSize()); |
|
setSize(getSize()+1); |
|
//Serial.print("New Size: "); |
|
//Serial.println(getSize()); |
|
//Serial.print("Size of dataType"); |
|
//Serial.println(sizeof(dataType)); |
|
if (index != getSize()-1) { |
|
memmove(data+index+1,data+index,sizeof(dataType)/sizeof(char)*(getSize()-1-index)); |
|
//Serial.println("memmove called and completed"); |
|
} |
|
(*this)[index]=value; |
|
//Serial.println("insert done"); |
|
} |
|
// remove |
|
void remove(const size_t & index) { |
|
#ifdef ASSERT |
|
assert(index<size,vectorSource,__LINE__); |
|
#endif |
|
memmove(data+index,data+index+1,getSize()-index-1); |
|
setSize(getSize()-1); |
|
} |
|
// push_back |
|
void push_back(const dataType & value) { |
|
//Serial.println("push_back called"); |
|
insert(getSize(),value); |
|
//Serial.println("push_back done"); |
|
} |
|
// pop_front |
|
dataType & pop_front() { |
|
dataType tmp = (*this)[0]; |
|
remove(0); |
|
return tmp; |
|
} |
|
// push_back a vector |
|
void push_back(const Vector & vector) { |
|
for (size_t i=0; i<vector.getSize(); i++) |
|
push_back(vector[i]); |
|
} |
|
// const array access operator |
|
const dataType & operator[](const size_t & index) const { |
|
#ifdef ASSERT |
|
assert(index<getSize(),vectorSource,__LINE__); |
|
#endif |
|
return data[index]; |
|
} |
|
// array access operator |
|
dataType & operator[](const size_t & index) { |
|
#ifdef ASSERT |
|
assert(index<getSize(),vectorSource,__LINE__); |
|
#endif |
|
return data[index]; |
|
} |
|
// assignment operator |
|
Vector & operator=(const Vector & v) { |
|
setSize(v.getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)[i]=v[i]; |
|
return *this; |
|
} |
|
// equal |
|
const bool operator==(const Vector& v) const { |
|
#ifdef ASSERT |
|
assert(getSize()==v.getSize(),vectorSource,__LINE__); |
|
#endif |
|
for (size_t i=0; i<getSize(); i++) { |
|
if ((*this)[i]!=v[i]) return false; |
|
} |
|
return true; |
|
} |
|
// not equal |
|
const bool operator!=(const Vector& v) const { |
|
return !((*this)==v); |
|
} |
|
// addition |
|
const Vector operator+(const Vector& v) const { |
|
#ifdef ASSERT |
|
assert(v.getSize() == getSize(),vectorSource,__LINE__); |
|
#endif |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result(i)=(*this)[i]+v[i]; |
|
return result; |
|
} |
|
// addition |
|
const Vector operator+(const dataType& s) const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result[i]=(*this)[i]+s; |
|
return result; |
|
} |
|
// subtraction |
|
const Vector operator-(const Vector& v) const { |
|
#ifdef ASSERT |
|
assert(v.getSize() == getSize(),vectorSource,__LINE__); |
|
#endif |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result[i]=(*this)[i]-v[i]; |
|
return result; |
|
} |
|
// negation |
|
const Vector operator-() const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result[i]=-(*this)[i]; |
|
return result; |
|
} |
|
// += |
|
Vector& operator+=(const Vector& v) { |
|
#ifdef ASSERT |
|
assert(v.getSize() == getSize(),vectorSource,__LINE__); |
|
#endif |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)(i)+=v(i); |
|
return *this; |
|
} |
|
// -= |
|
Vector& operator-=( const Vector& v) { |
|
#ifdef ASSERT |
|
assert(v.getSize() == getSize(),vectorSource,__LINE__); |
|
#endif |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)(i)-=v(i); |
|
return *this; |
|
} |
|
// elementwise mult. |
|
const Vector operator*(const Vector & v) const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result(i)=(*this)(i)*v(i); |
|
return result; |
|
} |
|
|
|
// mult. by a scalar |
|
const Vector operator*(const dataType & s) const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result(i)=(*this)(i)*s; |
|
return result; |
|
} |
|
// div. by a scalar |
|
const Vector operator/(const dataType & s) const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result(i)=(*this)(i)/s; |
|
return result; |
|
} |
|
// elementwise div. |
|
const Vector operator/(const Vector & v) const { |
|
Vector result(getSize()); |
|
for (size_t i=0; i<getSize(); i++) |
|
result(i)=(*this)(i)/v(i); |
|
return result; |
|
} |
|
|
|
// div. by a scalar |
|
Vector & operator/=(const dataType & s) { |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)(i)/=s; |
|
return *this; |
|
} |
|
// mult. by a scalar |
|
Vector & operator*=(const dataType & s) { |
|
for (size_t i=0; i<getSize(); i++) |
|
(*this)(i)*=s; |
|
return *this; |
|
} |
|
// cross/vector product |
|
const Vector cross(const Vector& v) const { |
|
Vector result(3), u=*this; |
|
#ifdef ASSERT |
|
assert(u.getSize()==3 && v.getSize()==3,vectorSource,__LINE__); |
|
#endif |
|
result(0) = u(1)*v(2)-u(2)*v(1); |
|
result(1) = -u(0)*v(2)+u(2)*v(0); |
|
result(2) = u(0)*v(1)-u(1)*v(0); |
|
return result; |
|
} |
|
// dot/scalar product |
|
const dataType dot(const Vector& v) const { |
|
#ifdef ASSERT |
|
assert(getSize()==v.getSize(),vectorSource,__LINE__); |
|
#endif |
|
dataType result; |
|
for (size_t i=0; i<getSize(); i++) result += (*this)(i)*v(i); |
|
return result; |
|
} |
|
// norm |
|
const dataType norm() const { |
|
return sqrt(dot(*this)); |
|
} |
|
// unit vector |
|
const Vector unit() const { |
|
return (*this)*(1/norm()); |
|
} |
|
// sum |
|
const sumType sum(const size_t & start=0,const int & end=-1) const { |
|
size_t end2; |
|
if (end==-1) end2=getSize()-1; |
|
else end2=end; |
|
sumType _sum = 0; |
|
for (size_t i=start; i<=end2; i++) _sum += (*this)(i); |
|
return _sum; |
|
} |
|
void sumFletcher(uint8_t & CK_A, uint8_t & CK_B, const size_t & start=0,const int & end=-1) const { |
|
size_t end2; |
|
if (end==-1) end2=getSize()-1; |
|
else end2=end; |
|
|
|
for (size_t i = start; i<=end2; i++) { |
|
CK_A += (*this)(i); |
|
CK_B += CK_A; |
|
} |
|
} |
|
// range |
|
const Vector range(const size_t & start, const size_t & stop) const { |
|
Vector v(stop-start+1); |
|
for (size_t i=start; i<=stop; i++) v(i-start) = (*this)(i); |
|
return v; |
|
} |
|
// to Array |
|
const dataType* toArray() const { |
|
dataType array[getSize()]; |
|
for (size_t i=0; i<getSize(); i++) array[i] = (*this)(i); |
|
return array; |
|
} |
|
// printing |
|
void print(Stream & serial=Serial, const char * msg="", size_t format=0) const { |
|
serial.print(msg); |
|
for (size_t i=0; i<getSize(); i++) { |
|
serial.print((*this)(i),format); |
|
serial.print(" "); |
|
} |
|
serial.println(); |
|
} |
|
// self test |
|
static bool selfTest(Stream & serial=Serial) { |
|
serial.println("Vector self test."); |
|
Vector u(3),v(3),w(3); |
|
u(0) = 1; |
|
u(1) = 2; |
|
u(2) = 3; |
|
v(0) = -4; |
|
v(1) = -5; |
|
v(2) = -6; |
|
u.print(serial,"u: "); |
|
v.print(serial,"v: "); |
|
(u+v).print(serial,"u + v: "); |
|
(u-v).print(serial,"u - v: "); |
|
Serial.print("u dot v: "); |
|
Serial.println(u.dot(v)); |
|
Serial.print("size of u: "); |
|
Serial.println(u.getSize()); |
|
Serial.print("size of v: "); |
|
Serial.println(v.getSize()); |
|
w=u.cross(v); |
|
w.print(serial,"u cross v: "); |
|
Serial.print("size of u cross v: "); |
|
Serial.println(w.getSize()); |
|
return true; |
|
} |
|
|
|
}; |
|
|
|
#endif |
|
|
|
// vim:ts=4:sw=4:expandtab
|
|
|