vectors.h
Go to the documentation of this file.
1 /********************************************************************************
2  * Neural Network Framework. *
3  * Copyright (C) 2005-2011 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #ifndef VECTORS_H
21 #define VECTORS_H
22 
28 #include "memutils.h"
29 #include "QVector"
30 #include "nnfwexceptions.h"
31 
32 namespace farsa {
33 
41 class FARSA_NNFW_TEMPLATE doubleRef {
42 public:
44  doubleRef() : ref(&dummy), ref2(&dummy) {
45  };
47  operator double() {
48  return *ref;
49  };
51  doubleRef& operator=( const doubleRef& src ) {
52  ref2 = src.ref2;
53  return (*this);
54  };
56  doubleRef& operator=( const double& src ) {
57  *ref2 = src;
58  return (*this);
59  };
61  doubleRef& operator+=( const double& src ) {
62  *ref2 += src;
63  return (*this);
64  };
66  doubleRef& operator-=( const double& src ) {
67  *ref2 -= src;
68  return (*this);
69  };
71  doubleRef& operator*=( const double& src ) {
72  *ref2 *= src;
73  return (*this);
74  };
76  doubleRef& operator/=( const double& src ) {
77  *ref2 /= src;
78  return (*this);
79  };
81  void setRef( double* src) {
82  ref = src;
83  ref2 = src;
84  };
86  void setNoSteady() {
87  ref2 = ref;
88  };
90  void setSteady() {
91  ref2 = &dummy;
92  };
94  bool isSteady() {
95  return ref != ref2;
96  };
97 private:
98  //--- How it works:
99  //--- ref is always returned when the data is retrieved,
100  //--- while ref2 is used during all assignments operation
101  //--- FIXED data: ref2 points to dummy variable, in this way each assignment will change
102  //--- the dummy variable and not the data pointed by ref
103  //--- NOT FIXED : ref2 points to same variable of ref, in this way each assignement will change
104  //--- the data pointed by ref (i.e. the source data)
105  double* ref;
106  double* ref2;
107  static double dummy;
108 };
109 
121 class FARSA_NNFW_TEMPLATE DoubleVector {
122 public:
125  shData = new sharedData();
126  shData->vsize = 0;
127  //shData->data = 0;
128  //shData->dataref = 0;
129  shData->refcounts = 1;
130  shData->temporary = false;
131  shData->nodata = false;
132  this->isinternal = false;
133  };
138  DoubleVector( unsigned int size, bool isinternal = false ) {
139  shData = new sharedData();
140  shData->vsize = size;
141  shData->data = new double[size];
142  memoryZeroing( shData->data, size );
143  shData->dataref = new doubleRef[size];
144  shData->refcounts = 1;
145  shData->temporary = false;
146  shData->nodata = false;
147  for( unsigned int i=0; i<shData->vsize; i++ ) {
148  shData->dataref[i].setRef( shData->data + i );
149  }
150  this->isinternal = isinternal;
151  };
156  DoubleVector( unsigned int size, double value, bool isinternal = false ) {
157  shData = new sharedData();
158  shData->vsize = size;
159  shData->data = new double[size];
160  shData->dataref = new doubleRef[size];
161  shData->refcounts = 1;
162  shData->temporary = false;
163  shData->nodata = false;
164  for( unsigned int i=0; i<shData->vsize; i++ ) {
165  shData->data[i] = value;
166  shData->dataref[i].setRef( shData->data + i );
167  }
168  this->isinternal = isinternal;
169  };
174  DoubleVector( const double* r, unsigned int dim, bool isinternal = false ) {
175  shData = new sharedData();
176  shData->vsize = dim;
177  shData->data = new double[dim];
178  shData->dataref = new doubleRef[dim];
179  shData->refcounts = 1;
180  shData->temporary = false;
181  shData->nodata = false;
182  for( unsigned int i=0; i<shData->vsize; i++ ) {
183  shData->data[i] = r[i];
184  shData->dataref[i].setRef( shData->data + i );
185  }
186  this->isinternal = isinternal;
187  };
189  DoubleVector( const DoubleVector& src ) {
190  shData = src.shData;
191  shData->refcounts += 1;
192  //--- is not a temporary anymore !
193  shData->temporary = false;
194  isinternal = false;
195  };
225  DoubleVector( unsigned int dim, bool temp, unsigned int dummy ) {
226  (void)dummy; // This stops warnings. Assigning dummy a value would have produce a "parameter ‘dummy’ set but not used" warning
227  shData = new sharedData();
228  shData->vsize = dim;
229  shData->data = new double[dim];
230  shData->dataref = new doubleRef[dim];
231  shData->refcounts = 1;
232  shData->temporary = temp;
233  shData->nodata = false;
234  for( unsigned int i=0; i<shData->vsize; i++ ) {
235  shData->dataref[i].setRef( shData->data + i );
236  }
237  this->isinternal = false;
238  };
241  shData->refcounts -= 1;
242  if ( shData->refcounts == 0 ) {
243  //--- the last destroy the data
244  if ( shData->vsize > 0 ) {
245  delete [](shData->dataref);
246  if ( !(shData->nodata) ) {
247  delete [](shData->data);
248  }
249  }
250  delete shData;
251  }
252  };
254  unsigned int size() const {
255  return shData->vsize;
256  };
258  bool isNull() const {
259  return (shData->vsize==0);
260  };
262  bool operator==( const DoubleVector& b ) const {
263  if ( shData == b.shData ) return true;
264  if ( shData->vsize != b.shData->vsize ) return false;
265  for( unsigned int i=0; i<shData->vsize; i++ ) {
266  if ( shData->dataref[i] != b.shData->dataref[i] ) return false;
267  }
268  return true;
269  };
271  bool operator!=( const DoubleVector& b ) const {
272  return !( *this == b );
273  };
281  if ( isinternal ) throw VectorAssignmentNotAllowed();
282  if ( src.shData == shData ) return (*this);
283  //--- eliminate the previous data
284  shData->refcounts -= 1;
285  if ( shData->refcounts == 0 ) {
286  //--- the last destroy the data
287  if ( shData->vsize > 0 ) {
288  delete [](shData->dataref);
289  if ( !(shData->nodata) ) {
290  delete [](shData->data);
291  }
292  }
293  delete shData;
294  }
295  //--- set the new data taken from src
296  shData = src.shData;
297  shData->refcounts++;
298  //--- is not a temporary anymore !
299  shData->temporary = false;
300  return (*this);
301  };
310  // if shared data is the same, they already share the same values
311  if ( shData == src.shData ) return (*this);
312  detach();
313  unsigned int max = qMin( shData->vsize, src.size() );
314  for( unsigned int i=0; i<max; i++ ) {
315  shData->dataref[i] = src[i];
316  }
317  return (*this);
318  };
326  DoubleVector& copyValues( const QVector<double>& src ) {
327  detach();
328  unsigned int max = qMin( shData->vsize, (unsigned int)(src.size()) );
329  for( unsigned int i=0; i<max; i++ ) {
330  shData->dataref[i] = src[i];
331  }
332  return (*this);
333  };
341  DoubleVector& copyValues( const DoubleVector& src, unsigned int srcOffset, unsigned int thisOffset ) {
342  // if shared data is the same and offsets are zero, then there is nothing to do
343  if ( shData == src.shData && srcOffset == 0 && thisOffset == 0 ) return (*this);
344  detach();
345  unsigned int max = qMin( shData->vsize-thisOffset, src.size()-srcOffset );
346  for( unsigned int i=0; i<max; i++ ) {
347  shData->dataref[i+thisOffset] = src[i+srcOffset];
348  }
349  return (*this);
350  };
362  DoubleVector& copyValues( const DoubleVector& src, unsigned int srcOffset, unsigned int thisOffset, unsigned int stride ) {
363  if ( stride == 0 ) return (*this);
364  // if shared data is the same and offsets are zero, then there is nothing to do
365  if ( shData == src.shData && srcOffset == 0 && thisOffset == 0 ) return (*this);
366  detach();
367  unsigned int max = qMin( shData->vsize-thisOffset, src.size()-srcOffset );
368  for( unsigned int i=0; i<max; i=i+stride ) {
369  shData->dataref[i+thisOffset] = src[i+srcOffset];
370  }
371  return (*this);
372  };
377  if ( shData->refcounts > 1 ) {
378  sharedData* tmp = new sharedData();
379  unsigned int size = shData->vsize;
380  tmp->vsize = size;
381  tmp->data = new double[size];
382  if ( shData->nodata ) {
383  for( unsigned int i=0; i<size; i++ ) {
384  tmp->data[i] = shData->dataref[i];
385  }
386  } else {
387  memoryCopy( tmp->data, shData->data, size );
388  }
389  tmp->dataref = new doubleRef[size];
390  tmp->refcounts = 1;
391  tmp->temporary = false;
392  tmp->nodata = false;
393  for( unsigned int i=0; i<size; i++ ) {
394  tmp->dataref[i].setRef( tmp->data + i );
395  }
396  shData->refcounts--;
397  shData = tmp;
398  }
399  return (*this);
400  };
402  const DoubleVector& operator+() const {
403  return (*this);
404  };
406  const DoubleVector operator-() const {
407  if ( shData->temporary ) {
408  for( unsigned int i=0; i<shData->vsize; i++ ) {
409  shData->dataref[i] = -shData->dataref[i];
410  }
411  return (*this);
412  } else {
413  DoubleVector ret( shData->vsize, true, 0 );
414  for( unsigned int i=0; i<shData->vsize; i++ ) {
415  ret.shData->dataref[i] = -shData->dataref[i];
416  }
417  return ret;
418  }
419  };
423  const DoubleVector operator+( const DoubleVector& right ) const {
424 #ifdef FARSA_DEBUG
425  if ( shData->vsize != right.shData->vsize ) {
426  throw IncompatibleVectors("Incompatible DoubleVectors in operator+ (dimension must be equals)");
427  }
428 #endif
429  if ( right.shData->temporary ) {
430  for( unsigned int i=0; i<shData->vsize; i++ ) {
431  right.shData->dataref[i] = shData->dataref[i] + right.shData->dataref[i];
432  }
433  return right;
434  } else if ( shData->temporary ) {
435  for( unsigned int i=0; i<shData->vsize; i++ ) {
436  shData->dataref[i] = shData->dataref[i] + right.shData->dataref[i];
437  }
438  return (*this);
439  } else {
440  DoubleVector ret( shData->vsize, true, 0 );
441  for( unsigned int i=0; i<shData->vsize; i++ ) {
442  ret.shData->dataref[i] = shData->dataref[i] + right.shData->dataref[i];
443  }
444  return ret;
445  }
446  };
450  const DoubleVector operator-( const DoubleVector& right ) const {
451 #ifdef FARSA_DEBUG
452  if ( shData->vsize != right.shData->vsize ) {
453  throw IncompatibleVectors("Incompatible DoubleVectors in operator- (dimension must be equals)");
454  }
455 #endif
456  if ( right.shData->temporary ) {
457  for( unsigned int i=0; i<shData->vsize; i++ ) {
458  right.shData->dataref[i] = shData->dataref[i] - right.shData->dataref[i];
459  }
460  return right;
461  } else if ( shData->temporary ) {
462  for( unsigned int i=0; i<shData->vsize; i++ ) {
463  shData->dataref[i] = shData->dataref[i] - right.shData->dataref[i];
464  }
465  return (*this);
466  } else {
467  DoubleVector ret( shData->vsize, true, 0 );
468  for( unsigned int i=0; i<shData->vsize; i++ ) {
469  ret.shData->dataref[i] = shData->dataref[i] - right.shData->dataref[i];
470  }
471  return ret;
472  }
473  };
477  const DoubleVector operator*( const DoubleVector& right ) const {
478 #ifdef FARSA_DEBUG
479  if ( shData->vsize != right.shData->vsize ) {
480  throw IncompatibleVectors("Incompatible DoubleVectors in operator* (dimension must be equals)");
481  }
482 #endif
483  if ( right.shData->temporary ) {
484  for( unsigned int i=0; i<shData->vsize; i++ ) {
485  right.shData->dataref[i] = shData->dataref[i] * right.shData->dataref[i];
486  }
487  return right;
488  } else if ( shData->temporary ) {
489  for( unsigned int i=0; i<shData->vsize; i++ ) {
490  shData->dataref[i] = shData->dataref[i] * right.shData->dataref[i];
491  }
492  return (*this);
493  } else {
494  DoubleVector ret( shData->vsize, true, 0 );
495  for( unsigned int i=0; i<shData->vsize; i++ ) {
496  ret.shData->dataref[i] = shData->dataref[i] * right.shData->dataref[i];
497  }
498  return ret;
499  }
500  };
504  const DoubleVector operator/( const DoubleVector& right ) const {
505 #ifdef FARSA_DEBUG
506  if ( shData->vsize != right.shData->vsize ) {
507  throw IncompatibleVectors("Incompatible DoubleVectors in operator/ (dimension must be equals)");
508  }
509 #endif
510  if ( right.shData->temporary ) {
511  for( unsigned int i=0; i<shData->vsize; i++ ) {
512  right.shData->dataref[i] = shData->dataref[i] / right.shData->dataref[i];
513  }
514  return right;
515  } else if ( shData->temporary ) {
516  for( unsigned int i=0; i<shData->vsize; i++ ) {
517  shData->dataref[i] = shData->dataref[i] / right.shData->dataref[i];
518  }
519  return (*this);
520  } else {
521  DoubleVector ret( shData->vsize, true, 0 );
522  for( unsigned int i=0; i<shData->vsize; i++ ) {
523  ret.shData->dataref[i] = shData->dataref[i] / right.shData->dataref[i];
524  }
525  return ret;
526  }
527  };
532 #ifdef FARSA_DEBUG
533  if ( shData->vsize != right.shData->vsize ) {
534  throw IncompatibleVectors("Incompatible DoubleVectors in operator+= (dimension must be equals)");
535  }
536 #endif
537  detach();
538  for( unsigned int i=0; i<shData->vsize; i++ ) {
539  shData->dataref[i] = shData->dataref[i] + right.shData->dataref[i];
540  }
541  return (*this);
542  };
547 #ifdef FARSA_DEBUG
548  if ( shData->vsize != right.shData->vsize ) {
549  throw IncompatibleVectors("Incompatible DoubleVectors in operator-= (dimension must be equals)");
550  }
551 #endif
552  detach();
553  for( unsigned int i=0; i<shData->vsize; i++ ) {
554  shData->dataref[i] = shData->dataref[i] - right.shData->dataref[i];
555  }
556  return (*this);
557  };
562 #ifdef FARSA_DEBUG
563  if ( shData->vsize != right.shData->vsize ) {
564  throw IncompatibleVectors("Incompatible DoubleVectors in operator*= (dimension must be equals)");
565  }
566 #endif
567  detach();
568  for( unsigned int i=0; i<shData->vsize; i++ ) {
569  shData->dataref[i] = shData->dataref[i] * right.shData->dataref[i];
570  }
571  return (*this);
572  };
577 #ifdef FARSA_DEBUG
578  if ( shData->vsize != right.shData->vsize ) {
579  throw IncompatibleVectors("Incompatible DoubleVectors in operator/= (dimension must be equals)");
580  }
581 #endif
582  detach();
583  for( unsigned int i=0; i<shData->vsize; i++ ) {
584  shData->dataref[i] = shData->dataref[i] / right.shData->dataref[i];
585  }
586  return (*this);
587  };
589  DoubleVector& operator+=( const double& right ) {
590  detach();
591  for( unsigned int i=0; i<shData->vsize; i++ ) {
592  shData->dataref[i] = shData->dataref[i] + right;
593  }
594  return (*this);
595  };
597  DoubleVector& operator-=( const double& right ) {
598  detach();
599  for( unsigned int i=0; i<shData->vsize; i++ ) {
600  shData->dataref[i] = shData->dataref[i] - right;
601  }
602  return (*this);
603  };
605  DoubleVector& operator*=( const double& right ) {
606  detach();
607  for( unsigned int i=0; i<shData->vsize; i++ ) {
608  shData->dataref[i] = shData->dataref[i] * right;
609  }
610  return (*this);
611  };
613  DoubleVector& operator/=( const double& right ) {
614  detach();
615  for( unsigned int i=0; i<shData->vsize; i++ ) {
616  shData->dataref[i] = shData->dataref[i] / right;
617  }
618  return (*this);
619  };
624  DoubleVector& steady( unsigned int i ) {
625 #ifdef FARSA_DEBUG
626  if( i >= shData->vsize ) {
627  throw OutsideVectorBoundaries("Fixating elements outside boundary");
628  }
629 #endif
630  detach();
631  shData->dataref[i].setSteady();
632  return (*this);
633  };
637  DoubleVector& unsteady( unsigned int i ) {
638 #ifdef FARSA_DEBUG
639  if( i >= shData->vsize ) {
640  throw OutsideVectorBoundaries("Un-Fixating elements outside boundary");
641  }
642 #endif
643  detach();
644  shData->dataref[i].setNoSteady();
645  return (*this);
646  };
650  bool isSteady( unsigned int i ) const {
651 #ifdef FARSA_DEBUG
652  if( i >= shData->vsize ) {
653  throw OutsideVectorBoundaries("isSteady - Accessing element outside boundary");
654  }
655 #endif
656  return shData->dataref[i].isSteady();
657  };
662  detach();
663  for( unsigned int i=0; i<shData->vsize; i++ ) {
664  shData->dataref[i] = 0;
665  }
666  return (*this);
667  };
671  DoubleVector& setAll( const double value ) {
672  detach();
673  for( unsigned int i=0; i<shData->vsize; i++ ) {
674  shData->dataref[i] = value;
675  }
676  return (*this);
677  };
681  doubleRef& operator[]( unsigned int index ) {
682 #ifdef FARSA_DEBUG
683  if( index >= shData->vsize ) {
684  throw OutsideVectorBoundaries("operator[] - Accessing elements outside boundary");
685  }
686 #endif
687  detach();
688  return shData->dataref[index];
689  };
693  double operator[]( unsigned int index ) const {
694 #ifdef FARSA_DEBUG
695  if( index >= shData->vsize ) {
696  throw OutsideVectorBoundaries("operator[] - Accessing elements outside boundary");
697  }
698 #endif
699  return shData->dataref[index];
700  };
702  DoubleVector& resize( unsigned int newsize ) {
703  if ( shData->nodata || isinternal ) {
704  throw VectorResizeNotAllowed();
705  }
706  detach();
707  if ( newsize > shData->vsize ) {
708  double* newdata = new double[newsize];
709  memoryCopy( newdata, shData->data, shData->vsize );
710  delete [](shData->data);
711  delete [](shData->dataref);
712  shData->data = newdata;
713  shData->vsize = newsize;
714  shData->dataref = new doubleRef[ newsize ];
715  for( unsigned int i=0; i<shData->vsize; i++ ) {
716  shData->dataref[i].setRef( shData->data + i );
717  }
718  } else {
719  shData->vsize = newsize;
720  }
721  return (*this);
722  };
724  DoubleVector& append( const double& value ) {
725  //--- detach (and throw) done by resize
726  resize( shData->vsize+1 );
727  shData->data[ shData->vsize-1 ] = value;
728  return (*this);
729  };
731  DoubleVector& operator<<( const double& value ) {
732  //--- detach (and throw) done by resize (append)
733  append( value );
734  return (*this);
735  };
736 
737 private:
738  class sharedData {
739  public:
741  unsigned int vsize;
743  double* data;
745  int refcounts;
747  doubleRef* dataref;
749  bool temporary;
751  bool nodata;
752  };
754  sharedData* shData;
759  bool isinternal;
760 
761  friend class DoubleMatrix;
767  void resizeNoData( unsigned int newsize ) {
768  if ( shData->vsize > 0 ) {
769  if ( shData->data ) { delete [](shData->data); }
770  delete [](shData->dataref);
771  }
772  shData->vsize = newsize;
773  shData->dataref = new doubleRef[ newsize ];
774  shData->nodata = true;
775  isinternal = true;
776  };
777 };
778 
779 }
780 
781 #endif