SM_ADC  1.0
Приём данных АЦП через разделяемую память
array.h
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 //
3 // This file is part of easyLink Library.
4 //
5 // Copyright (c) 2014 FEMTO-ST, ENSMM, UFC, CNRS.
6 //
7 // License: GNU General Public License 3
8 // Author: Guillaume J. Laurent
9 //
10 //------------------------------------------------------------------------------
11 #ifndef EASYLINK_ARRAY_H
12 #define EASYLINK_ARRAY_H
13 
14 //------------------------------------------------------------------------------
15 #include "utils.h"
16 #include <string>
17 #include <stdexcept>
18 using namespace std;
19 
20 //------------------------------------------------------------------------------
21 /** Array is the fundamental class underlying easyLink data manipulation.
22  *
23  * Array is used to access simulink input, output and parameter ports as well
24  * as MATLAB matrix and mxArray.
25  *
26  * Array provides intuitive functions and operators to perform various
27  * operations using a MATLAB like interface.
28  */
29 class Array
30 {
31 public:
32 
33  /** Default constructor. */
34  Array(string name="untitled array")
35  {
36  nrows=0;
37  ncols=0;
38  mxarray=NULL;
39  data=NULL;
40  this->name=name;
41  moveable=false;
42  releaseData=false;
43 #ifdef __TEST__
44  printf("easyLink test message: constructing empty array called \"%s\".\n",getFullName().c_str());
45 #endif
46  }
47 
48  /** Construct an Array and allocate memory for data.
49  *
50  * Set moveable to true if the Array is used as a return value (and
51  * to avoid data copy in this case). */
52  Array(int nrows,int ncols=1,string name="untitled array",bool moveable=false)
53  {
54  this->nrows=nrows;
55  this->ncols=ncols;
56  this->mxarray=NULL;
57  this->data=new double[nrows*ncols];
58  this->name=name;
59  this->moveable=moveable;
60  this->releaseData=true;
61  memset((void*)data,0,nrows*ncols*sizeof(double));
62 #ifdef __TEST__
63  allocationNumber++;
64  printf("easyLink test message: constructing array called \"%s\".\n",getFullName().c_str());
65 #endif
66  }
67 
68  /** Construct an Array using an existing mxArray.
69  * The constructor do NOT allocate and NOT copy the data if dataCopy is false.
70  *
71  * Set moveable to true if the Array is used as a return value (and
72  * to avoid data copy in this case). */
73  Array(const mxArray *mxarray,string name="untitled mxArray",bool moveable=false,bool dataCopy=false)
74  {
75  if (mxIsSparse(mxarray)||!mxIsDouble(mxarray))
76  throw runtime_error("easyLink error: the array must be a dense array of real values.");
77 
78  this->nrows=(int)mxGetM(mxarray);
79  this->ncols=(int)mxGetN(mxarray);
80  if (dataCopy)
81  {
82  this->mxarray=NULL;
83  this->data=new double[nrows*ncols];
84  memcpy((void*)data,(void*)mxGetPr(mxarray), nrows*ncols*sizeof(double) );
85  this->releaseData=true;
86 #ifdef __TEST__
87  allocationNumber++;
88 #endif
89  }
90  else
91  {
92  this->mxarray=(mxArray*)mxarray;
93  this->data=mxGetPr(mxarray);
94  this->releaseData=false;
95  }
96  this->name=name;
97  this->moveable=moveable;
98 #ifdef __TEST__
99  printf("easyLink test message: constructing array (using allocated mxarray) called \"%s\".\n",getFullName().c_str());
100 #endif
101  }
102 
103  /** Construct an Array with already allocated data without using mxArray.
104  * The constructor do NOT allocate and NOT copy the data.
105  *
106  * Set moveable to true if the Array is used as a return value (and
107  * to avoid data copy in this case).
108  *
109  * Set releaseData to true if the Array must free the memory during deletion. */
110  Array(const double *data,int nrows,int ncols=1,string name="untitled data",bool moveable=false,bool releaseData=false)
111  {
112  this->nrows=nrows;
113  this->ncols=ncols;
114  this->mxarray=NULL;
115  this->data=(double*)data;
116  this->name=name;
117  this->moveable=moveable;
118  this->releaseData=releaseData;
119 #ifdef __TEST__
120  printf("easyLink test message: constructing array (using allocated double array) \"%s\".\n",getFullName().c_str());
121 #endif
122  }
123 
124  /** Copy constructor. The method generally does a copy of the data. If the
125  * argument is moveable, the data are stolen to this argument before its
126  * deletion (no data copy). */
127  Array(const Array &array)
128  {
129  if (array.moveable)
130  stealData(array);
131  else
132  {
133 #ifdef __TEST__
134  printf("easyLink test message: hard copy of array \"%s\" in copy constructor.\n",array.name.c_str());
135 #endif
136  copyOf(array);
137  }
138  }
139 
140  /** Move constructor. C++ 2011 only.*/
141 #ifdef __CPP2011__
142  Array(const Array && array)
143  {
144  stealData(array);
145  }
146 #endif
147 
148  /** Destructor. Free the memory if not shared. */
150  {
151 #ifdef __TEST__
152  printf("easyLink test message: destroying \"%s\".\n",getFullName().c_str());
153 #endif
154  empty();
155  }
156 
157  /** Empty the array and free the memory if owned. */
158  void empty()
159  {
160  if (releaseData)
161  {
162 #ifdef __TEST__
163  allocationNumber--;
164 #endif
165  delete [] data;
166  }
167  nrows=0;
168  ncols=0;
169  mxarray=NULL;
170  data=NULL;
171  moveable=false;
172  releaseData=false;
173  }
174 
175  /** Array assignment. The method generally does a copy of the data. If the
176  * argument is moveable, the data are stolen to this argument before its
177  * deletion (no data copy).
178  *
179  * Throws an exception if the data is shared and sizes don't match. */
180  void operator=(const Array &array)
181  {
182  if (nrows==0 && ncols==0) // empty array
183  {
184  if (array.moveable)
185  stealData(array);
186  else
187  {
188 #ifdef __TEST__
189  printf("easyLink test message: hard copy in assignment \"%s=%s\".\n",name.c_str(),array.name.c_str());
190 #endif
191  copyOf(array);
192  }
193  }
194  else if (releaseData)
195  {
196  if (array.moveable)
197  {
198  empty();
199  stealData(array);
200  }
201  else if (nrows==array.nrows && ncols==array.ncols)
202  {
203 #ifdef __TEST__
204  printf("easyLink test message: hard copy in assignment \"%s=%s\".\n",name.c_str(),array.name.c_str());
205 #endif
206  memcpy((void*)data,(void*)array.data, nrows*ncols*sizeof(double) );
207  }
208  else
209  {
210 #ifdef __TEST__
211  printf("easyLink test message: hard copy in assignment \"%s=%s\".\n",name.c_str(),array.name.c_str());
212 #endif
213  empty();
214  copyOf(array);
215  }
216  }
217  else // shared data
218  {
219  if (nrows!=array.nrows || ncols!=array.ncols)
220  throw runtime_error("easyLink error: Unable to assign "+array.name+" to shared array "+name+". Array dimensions must agree.");
221 
222 #ifdef __TEST__
223  printf("easyLink test message: hard copy in assignment \"%s=%s\".\n",name.c_str(),array.name.c_str());
224 #endif
225  memcpy((void*)data,(void*)array.data, nrows*ncols*sizeof(double) );
226  }
227  }
228 
229  /** Move assignment. C++ 2011 only. */
230 #ifdef __CPP2011__
231  void operator=(const Array &&array)
232  {
233  if (nrows==0 && ncols==0) // empty array
234  {
235  stealData(array);
236  }
237  else if (releaseData)
238  {
239  empty();
240  stealData(array);
241  }
242  else // shared data
243  {
244  if (nrows!=array.nrows || ncols!=array.ncols)
245  throw runtime_error("easyLink error: Unable to move assign "+array.name+" to shared array "+name+". Array dimensions must agree.");
246 
247 #ifdef __TEST__
248  printf("easyLink test message: hard copy in assignment \"%s=%s\".\n",name.c_str(),array.name.c_str());
249 #endif
250  memcpy((void*)data,(void*)array.data, nrows*ncols*sizeof(double) );
251  }
252  }
253 #endif
254 
255  /** Returns the address of the data. */
256  double* getData()
257  {
258  return data;
259  }
260 
261  /** Returns a copy of the array within a mxArray (data copy).
262  *
263  * The obtained mxArray must be released using mxDestroyArray. */
264  mxArray* getmxArrayCopy() const
265  {
266  mxArray *copy;
267  copy=mxCreateDoubleMatrix(nrows,ncols,mxREAL);
268  memcpy((void*)mxGetPr(copy),(void*)data, nrows*ncols*sizeof(double) );
269  return copy;
270  }
271 
272  /** Returns true is the array does not own the data. */
273  bool isShared()
274  {
275  return !releaseData;
276  }
277 
278  /** Returns the number of elements of the array.
279  * For 1-D array with w elements, this method returns w.
280  * For M-by-N array, this method returns m*n. */
281  int getWidth()
282  {
283  return nrows*ncols;
284  }
285 
286  /** Returns the number of columns of the array. */
287  int getNCols()
288  {
289  return ncols;
290  }
291 
292  /** Returns the number of rows of the array. */
293  int getNRows()
294  {
295  return nrows;
296  }
297 
298  /** Returns the name of the array. */
299  string getName()
300  {
301  return name;
302  }
303 
304  /** Read/write access to the element i of the array.
305  * i can go from 0 to nrows*ncols-1.
306  * Range errors throw an exception. */
307  double & operator[](int i)
308  {
309  if ( (i<0) || (i>=nrows*ncols) )
310  throw range_error("easyLink error: index exceeds array dimensions when accessing to "+name+"["+toString(i)+"].");
311  return *(data+i);
312  }
313 
314  /** Read/write access to the element (row,col) of the array.
315  Range errors throw an exception. */
316  double & operator()(int row,int col)
317  {
318  if ( (row<0) || (row>=nrows) || (col<0) || (col>=ncols) )
319  throw range_error("easyLink error: index exceeds array dimensions when accessing to "+name+"("+toString(row)+","+toString(col)+").");
320  return *(data+row+nrows*col);
321  }
322 
323  /** Initialization of all elements at the same value. */
324  void init(double x=0)
325  {
326  int i=nrows*ncols;
327  double* p=data;
328  for (; i--; p++)
329  *p=x;
330  }
331 
332  /** Reshaped to a new size with the same elements
333  * nrows*ncols must equal the number of elements of the array. */
334  void reshape(int nrows,int ncols)
335  {
336  if (this->nrows*this->ncols!=nrows*ncols)
337  throw runtime_error("easyLink error: unable to reshape "+name+".");
338 
339  this->nrows=nrows;
340  this->ncols=ncols;
341  }
342 
343  /** Print the array in the console. */
344  void print()
345  {
346 #ifdef __TEST__
347  printf(getFullName().c_str());
348 #else
349  printf(name.c_str());
350 #endif
351  printf(" = \n");
352  printf("[");
353  for (int row=0; row<nrows; row++)
354  {
355  for (int col=0; col<ncols; col++)
356  printf(" %7g",data[row+nrows*col]);
357 
358  if (row!=nrows-1)
359  printf("\n ");
360  }
361 
362  printf("]\n");
363  }
364 
365  /** Call internal MATLAB numeric functions, MATLAB operators,
366  * or user-defined functions and applied it to the array. */
367  Array callMatlab(string cmd)
368  {
369  mxArray *input,*output;
370 
371  if (mxarray==NULL)
372  input=getmxArrayCopy();
373  else
374  input=mxarray;
375 
376  mexCallMATLAB(1,&output,1,&input,cmd.c_str());
377 
378  Array result(output,cmd+"("+name+")",true,true);
379  mxDestroyArray(output);
380 
381  if (mxarray==NULL)
382  mxDestroyArray(input);
383 
384  return result;
385  }
386 
387  /** Call internal MATLAB numeric functions, MATLAB operators,
388  * or user-defined functions and applied it to the array and to a second
389  * operand. */
390  Array callMatlab(string cmd,const Array & operand2)
391  {
392  mxArray *input[2],*output;
393 
394  if (mxarray==NULL)
395  input[0]=getmxArrayCopy();
396  else
397  input[0]=mxarray;
398 
399  if (operand2.mxarray==NULL)
400  input[1]=operand2.getmxArrayCopy();
401  else
402  input[1]=operand2.mxarray;
403 
404  mexCallMATLAB(1,&output,2,input,cmd.c_str());
405 
406  Array result(output,cmd+"("+name+","+operand2.name+")",true,true);
407  mxDestroyArray(output);
408 
409  if (mxarray==NULL)
410  mxDestroyArray(input[0]);
411 
412  if (operand2.mxarray==NULL)
413  mxDestroyArray(input[1]);
414 
415  return result;
416  }
417 
418  /** Call internal MATLAB numeric functions, MATLAB operators,
419  * or user-defined functions and applied it to the array and to a second
420  * scalar operand. */
421  Array callMatlab(string cmd,double operand2)
422  {
423  mxArray *input[2],*output;
424 
425  if (mxarray==NULL)
426  input[0]=getmxArrayCopy();
427  else
428  input[0]=mxarray;
429 
430  input[1] = mxCreateDoubleMatrix(1,1,mxREAL);
431  *mxGetPr(mxarray)=operand2;
432  mexCallMATLAB(1,&output,2,input,cmd.c_str());
433 
434  Array result(output,cmd+"("+name+","+toString(operand2)+")",true,true);
435  mxDestroyArray(output);
436 
437  if (mxarray==NULL)
438  mxDestroyArray(input[0]);
439  mxDestroyArray(input[1]);
440 
441  return result;
442  }
443 
444  /** In-place element-by-element addition. */
445  void operator+=(double x)
446  {
447  int i=nrows*ncols;
448  double* p=data;
449  for (;i--;p++)
450  *p+=x;
451  }
452 
453  /** In-place element-by-element substraction. */
454  void operator-=(double x)
455  {
456  int i=nrows*ncols;
457  double* p=data;
458  for (;i--;p++)
459  *p-=x;
460  }
461 
462  /** In-place element-by-element multiplication. */
463  void operator*=(double x)
464  {
465  int i=nrows*ncols;
466  double* p=data;
467  for (;i--;p++)
468  *p*=x;
469  }
470 
471  /** In-place element-by-element division. */
472  void operator/=(double x)
473  {
474  int i=nrows*ncols;
475  double* p=data;
476  for (;i--;p++)
477  *p/=x;
478  }
479 
480  /** Array-double addition. */
481  Array operator+(double x)
482  {
483  Array result(*this);
484  result+=x;
485  result.moveable=true;
486  result.name="("+name+"+"+toString(x)+")";
487  return result;
488  }
489 
490  /** Array-double substraction. */
491  Array operator-(double x)
492  {
493  Array result(*this);
494  result-=x;
495  result.moveable=true;
496  result.name="("+name+"-"+toString(x)+")";
497  return result;
498  }
499 
500  /** Array-double multiplication. */
501  Array operator*(double x)
502  {
503  Array result(*this);
504  result*=x;
505  result.moveable=true;
506  result.name="("+name+"*"+toString(x)+")";
507  return result;
508  }
509 
510  /** Array-double division. */
511  Array operator/(double x)
512  {
513  Array result(*this);
514  result/=x;
515  result.moveable=true;
516  result.name="("+name+"/"+toString(x)+")";
517  return result;
518  }
519 
520  /** In-place element-by-element addition.
521  * Arrays must have the same dimensions. */
522  void operator+=(const Array & operand)
523  {
524  if (nrows!=operand.nrows || ncols!=operand.ncols)
525  throw runtime_error("easyLink error: Unable to add "+name+" and "+operand.name+". Array dimensions must agree.");
526 
527  int i=nrows*ncols;
528  double* p=data;
529  double* s=operand.data;
530  for (;i--;p++,s++)
531  *p+=(*s);
532  }
533 
534  /** In-place element-by-element substraction.
535  * Arrays must have the same dimensions. */
536  void operator-=(const Array & operand)
537  {
538  if (nrows!=operand.nrows || ncols!=operand.ncols)
539  throw runtime_error("easyLink error: Unable to substract "+name+" and "+operand.name+". Array dimensions must agree.");
540 
541  int i=nrows*ncols;
542  double* p=data;
543  double* s=operand.data;
544  for (;i--;p++,s++)
545  *p-=(*s);
546  }
547 
548  /** In-place element-by-element multiplication.
549  * Arrays must have the same dimensions. */
550  void operator*=(const Array & operand)
551  {
552  if (nrows!=operand.nrows || ncols!=operand.ncols)
553  throw runtime_error("easyLink error: Unable to multiply "+name+" and "+operand.name+". Array dimensions must agree.");
554 
555  int i=nrows*ncols;
556  double* p=data;
557  double* s=operand.data;
558  for (;i--;p++,s++)
559  *p*=(*s);
560  }
561 
562  /** In-place element-by-element division.
563  * Arrays must have the same dimensions. */
564  void operator/=(const Array & operand)
565  {
566  if (nrows!=operand.nrows || ncols!=operand.ncols)
567  throw runtime_error("easyLink error: Unable to divide "+name+" and "+operand.name+". Array dimensions must agree.");
568 
569  int i=nrows*ncols;
570  double* p=data;
571  double* s=operand.data;
572  for (;i--;p++,s++)
573  *p/=(*s);
574  }
575 
576  /** Array-array addition. */
577  Array operator+(const Array & operand)
578  {
579  return callMatlab("plus",operand);
580  }
581 
582  /** Array-array substraction. */
583  Array operator-(const Array & operand)
584  {
585  return callMatlab("minus",operand);
586  }
587 
588  /** Array-array multiplication (matrix product). */
589  Array operator*(const Array & operand)
590  {
591  return callMatlab("mtimes",operand);
592  }
593 
594  /** Element-by-element comparison.
595  * Returns true if the array contains the same values.
596  * Use areEqual to compare double values. */
597  bool operator==(const Array & operand)
598  {
599  bool result;
600  if (nrows*ncols!=operand.nrows*operand.ncols)
601  result=false;
602  else
603  {
604  int i=nrows*ncols;
605  double *p=data;
606  double *q=operand.data;
607  for (;i-- && areEqual(*p,*q);p++,q++)
608  ;
609  result=(i<0);
610  }
611  return result;
612  }
613 
614  /** Returns the maximal value of the array */
615  double getMax()
616  {
617  int i=nrows*ncols-1;
618  double *p=data;
619  double result=*p;
620  p++;
621  for (;i--;p++)
622  if (*p>result)
623  result=*p;
624 
625  return result;
626  }
627 
628  /** Returns the minimal value of the array */
629  double getMin()
630  {
631  int i=nrows*ncols-1;
632  double *p=data;
633  double result=*p;
634  p++;
635  for (;i--;p++)
636  if (*p<result)
637  result=*p;
638 
639  return result;
640  }
641 
642  /** Returns the additive inverse of the array. */
644  {
645  Array result(*this);
646  int i=nrows*ncols;
647  double* p=result.data;
648  for (;i--;p++)
649  *p=-(*p);
650  result.moveable=true;
651  result.name="-"+name;
652  return result;
653  }
654 
655  /** Returns the inverse of the array. */
657  {
658  return callMatlab("inv");
659  }
660 
661  /** Return the identity matrix. */
662  static Array eye(int nrows,int ncols,string name="eye array")
663  {
664  Array result(nrows,ncols,name,true);
665 
666  for(int i=0; i<min(nrows,ncols); i++)
667  { result(i,i) = 1;
668  }
669 
670  return result;
671  }
672 
673 protected:
674 
675  int ncols,nrows;
676  mxArray *mxarray;
677  double *data;
678  string name;
679  bool moveable,releaseData;
680 
681  inline void stealData(const Array & array)
682  {
683  nrows=array.nrows;
684  ncols=array.ncols;
685  mxarray=array.mxarray;
686  data=array.data;
687  name=array.name;
688  moveable=false;
689  releaseData=array.releaseData;
690  *(bool*)(&array.releaseData)=false; // Trick to write a member of a const argument
691  }
692 
693  inline void copyOf(const Array & array)
694  {
695  nrows=array.nrows;
696  ncols=array.ncols;
697  mxarray=NULL;
698  data=new double[nrows*ncols];
699  memcpy((void*)data,(void*)array.data, nrows*ncols*sizeof(double) );
700  name=string("copy of ")+array.name;
701  moveable=false;
702  releaseData=true;
703 #ifdef __TEST__
704  allocationNumber++;
705 #endif
706  }
707 
708  inline string getFullName()
709  {
710  string result=name+" ("+toString(nrows)+"x"+toString(ncols)+" ";
711 
712  if (moveable)
713  result+="moveable ";
714  if (releaseData)
715  result+="releaseData ";
716  if (mxarray!=NULL)
717  result+="mex array)";
718  else
719  result+="double array)";
720 
721  return result;
722  }
723 
724 #ifdef __TEST__
725 public:
726  static int allocationNumber;
727 #endif
728 };
729 
730 #ifdef __TEST__
731 int Array::allocationNumber = 0;
732 #endif
733 
734 /** Double-array addition. */
735 Array operator+(double x,Array & operand)
736 {
737  return operand.operator+(x);
738 }
739 
740 /** Double-array substraction. */
741 Array operator-(double x,Array & operand)
742 {
743  return operand.opposite().operator+(x);
744 }
745 
746 /** Double-array multiplication. */
747 Array operator*(double x,Array & operand)
748 {
749  return operand.operator*(x);
750 }
751 
752 //------------------------------------------------------------------------------
753 #endif
int getNRows()
Definition: array.h:293
bool areEqual(double x, double y, double tolerance=EQUALITY_TOLERANCE)
Definition: utils.h:91
void operator+=(const Array &operand)
Definition: array.h:522
void operator-=(double x)
Definition: array.h:454
Definition: array.h:29
bool operator==(const Array &operand)
Definition: array.h:597
double getMax()
Definition: array.h:615
bool releaseData
Definition: array.h:679
Array operator-(const Array &operand)
Definition: array.h:583
Array operator+(double x)
Definition: array.h:481
Array operator-(double x, Array &operand)
Definition: array.h:741
void operator/=(const Array &operand)
Definition: array.h:564
void print()
Definition: array.h:344
Array inverse()
Definition: array.h:656
mxArray * mxarray
Definition: array.h:676
void stealData(const Array &array)
Definition: array.h:681
static Array eye(int nrows, int ncols, string name="eye array")
Definition: array.h:662
Array callMatlab(string cmd, const Array &operand2)
Definition: array.h:390
Array operator*(const Array &operand)
Definition: array.h:589
void operator-=(const Array &operand)
Definition: array.h:536
double * data
Definition: array.h:677
string toString(T value)
Definition: utils.h:35
void operator*=(double x)
Definition: array.h:463
string name
Definition: array.h:678
void copyOf(const Array &array)
Definition: array.h:693
void empty()
Definition: array.h:158
void init(double x=0)
Definition: array.h:324
void operator/=(double x)
Definition: array.h:472
Array opposite()
Definition: array.h:643
void operator*=(const Array &operand)
Definition: array.h:550
mxArray * getmxArrayCopy() const
Definition: array.h:264
Array(int nrows, int ncols=1, string name="untitled array", bool moveable=false)
Definition: array.h:52
Array callMatlab(string cmd)
Definition: array.h:367
void reshape(int nrows, int ncols)
Definition: array.h:334
Array operator+(const Array &operand)
Definition: array.h:577
bool isShared()
Definition: array.h:273
double & operator()(int row, int col)
Definition: array.h:316
Array(const double *data, int nrows, int ncols=1, string name="untitled data", bool moveable=false, bool releaseData=false)
Definition: array.h:110
Array(const mxArray *mxarray, string name="untitled mxArray", bool moveable=false, bool dataCopy=false)
Definition: array.h:73
int getNCols()
Definition: array.h:287
Array callMatlab(string cmd, double operand2)
Definition: array.h:421
void operator=(const Array &array)
Definition: array.h:180
bool moveable
Definition: array.h:679
Array(const Array &array)
Definition: array.h:127
Array operator*(double x, Array &operand)
Definition: array.h:747
string getFullName()
Definition: array.h:708
string getName()
Definition: array.h:299
int ncols
Definition: array.h:675
double * getData()
Definition: array.h:256
double getMin()
Definition: array.h:629
Array operator+(double x, Array &operand)
Definition: array.h:735
~Array()
Definition: array.h:149
int getWidth()
Definition: array.h:281
Array operator/(double x)
Definition: array.h:511
Array operator*(double x)
Definition: array.h:501
double & operator[](int i)
Definition: array.h:307
Array operator-(double x)
Definition: array.h:491
int nrows
Definition: array.h:675
Array(string name="untitled array")
Definition: array.h:34
void operator+=(double x)
Definition: array.h:445