Jamoma API  0.6.0.a19
TTMatrixBase.h
Go to the documentation of this file.
1 /** @file
2 
3  @ingroup foundationLibrary
4 
5  @brief 2-dimensional matrix of compound values with N elements each.
6 
7  @details Each compound value stored in the matrix is known as a component.
8  The number of elements in each component is variable, enabling the storage of things like complex numbers or RGBA colors.
9  However, this element count for each component and their datatype is uniform across the entire matrix. @n@n
10 
11  Locations for individual components in the matrix are identified by (row, column) pairs.
12  These coordinates are translated internally into linear memory using <a href="http://en.wikipedia.org/wiki/Row-major_order#Column-major_order">column-major order</a>. @n@n
13 
14  All dimension indices begin counting at zero.
15  This means that index values greater than or equal to the respective mRowCount, mColumnCount or mElementCount will be out of bounds. @n@n
16 
17  Please note that previous support for N dimensions has been deprecated and the TTMatrixBase class is now fixed at 2 dimensions.
18  Throughout this documentation, dimension 1 is referred to as the "row" and dimension 2 is referred to as the "column".
19 
20  @author Timothy Place & Nathan Wolek
21 
22  @copyright Copyright © 2011-2012, Timothy Place & Nathan Wolek @n
23  This code is licensed under the terms of the "New BSD License" @n
24  http://creativecommons.org/licenses/BSD/
25  */
26 
27 #ifndef __TT_MATRIX_BASE_H__
28 #define __TT_MATRIX_BASE_H__
29 
30 #include "TTFoundation.h"
31 #include "TTDataObjectBase.h"
32 #include "TTLimits.h"
33 
34 
35 /****************************************************************************************************/
36 // Class Specification
37 /** 2-dimensional matrix of compound values with N elements each.
38 
39  Each compound value stored in the matrix is known as a component. The number of elements in each component is variable, enabling the storage of things like complex numbers or RGBA colors. However, this element count for each component and their datatype is uniform across the entire matrix.
40 */
41 class TTFOUNDATION_EXPORT TTMatrixBase : public TTDataObjectBase {
43 
44 protected:
45 
46  TTBytePtr mData; ///< memory used to store matrix values
47  TTRowID mRowCount; ///< How many rows of values the matrix should have. Uses an signed 32-bit integer which provides a maximum value of 2,147,483,647.
48  TTColumnID mColumnCount; ///< How many columns of values the matrix should have. Uses an signed 32-bit integer which provides a maximum value of 2,147,483,647.
49  TTElementID mElementCount; ///< How many elements (parts) per value (e.g. 2 for complex numbers, 4 for colors, default = 1). Uses an signed 16-bit integer which provides a maximum value of 32,767.
50  TTUInt32 mComponentCount; ///< mRowCount * mColumnCount
51  TTUInt32 mComponentStride; ///< how many bytes from one the beginning one matrix component to the next
52  TTUInt32 mDataCount; ///< mComponentCount * mElementCount (e.g. total number of floats or ints in the matrix)
53  TTDataType mType; ///< member of global enumerated list #TTBase::#TTDataType (i.e., kTypeUInt8, kTypeUInt16, kTypeInt32, kTypeUInt64, kTypeFloat32, kTypeFloat64)
54  TTDataInfoPtr mTypeAsDataInfo; ///< pointer to info about the data type found in #TTBase::#ttDataTypeInfo
55  TTSymbol mTypeAsSymbol; ///< symbol with data type name for the public interface
56  TTUInt8 mTypeSizeInBytes; ///< number of bytes present in mType
57  TTUInt32 mDataSize; ///< mTypeSizeInBytes * mDataCount
58  TTBoolean mDataIsLocallyOwned; ///< If false, then we are referencing outside memory which we don't own
59 
60 
61  /** Internal method that resizes memory allocated when various attributes change.
62  @return TTErr kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone */
63  TTErr resize();
64 
65  /** Unit test for the window function unit.
66  @param returnedTestInfo The outcome from the performed unit test.
67  @return #TTErr error code if the method fails to execute, else #kTTErrNone.
68  */
69  virtual TTErr test(TTValue& returnedTestInfo);
70 
71  /** Internal method that sets the value for RowCount without resizing the matrix of values. It is included so that other methods in the class use consistent range checking. Values that are less than 1 will return false and leave the value unchanged.
72  @param aNewRowCount number of desired rows in this matrix
73  @return TTBoolean false if value was outside allowed range and therefore not changed, otherwise true
74  */
75  TTBoolean setRowCountWithoutResize(TTRowID aNewRowCount);
76 
77  /** Internal method that sets the value for ColumnCount without resizing the matrix of values. It is included so that other methods in the class use consistent range checking. Values that are less than 1 will return false and leave the value unchanged.
78  @param aNewColumnCount number of desired columns in this matrix
79  @return TTBoolean false if value was outside allowed range and therefore not changed, otherwise true
80  */
81  TTBoolean setColumnCountWithoutResize(TTColumnID aNewColumnCount);
82 
83  /** Internal method that sets the value for ElementCount without resizing the matrix of values. It is included so that other methods in the class use consistent range checking. Values that are less than 1 will return false and leave the value unchanged.
84  @param aNewElementCount number of desired elements in each component
85  @return TTBoolean false if value was outside allowed range and therefore not changed, otherwise true
86  */
87  TTBoolean setElementCountWithoutResize(TTElementID aNewElementCount);
88 
89  /** Internal method that sets the values for type-related variables without resizing the matrix of values. It is included so that other methods in the class consistently check for valid entries. Values that are not a defined numeric type in TTBase::ttDataTypeInfo will return false and leave the values unchanged.
90  @param aNewType desired TTDataType to be used for elements
91  @return TTBoolean false if value was outside allowed range and therefore not changed, otherwise true
92  */
93  TTBoolean setTypeWithoutResize(TTDataType aNewType);
94 
95 public:
96 
97  /** Attribute accessor. Sets the value for RowCount. Values that are less than 1 will return an error.
98  @param aNewRowCount number of desired rows in this matrix
99  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
100  */
101  TTErr setRowCount(const TTValue& aNewRowCount);
102 
103  /** Attribute accessor. Sets the value for ColumnCount. Values that are less than 1 will return an error.
104  @param aNewColumnCount number of desired columns in this matrix
105  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
106  */
107  TTErr setColumnCount(const TTValue& aNewColumnCount);
108 
109  /** Attribute accessor. Sets the value for ElementCount. Values that are less than 1 will return an error.
110  @param newElementCount number of desired elements in each component
111  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
112  */
113  TTErr setElementCount(const TTValue& newElementCount);
114 
115  /** Attribute accessor. Sets the value for type-related variables. Value must be a symbol that matches the name of a numeric type defined in TTBase::ttDataTypeInfo (i.e., float32, float64, int8, uint8, int16, uint16, int32, uint32, int64, uint64).
116  @param aType name of desired datatype to be used for each element
117  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
118  */
119  TTErr setType(const TTValue& aType);
120 
121  /** Attribute accessor. Set the values of mRowCount and mColumnCount using a TTValue array. Values beyond the first two items in the TTValue array will be ignored without an error. Values that are less than 1 will return an error. Support for N dimensions has been deprecated.
122  @param someNewDimensions a 2-item TTValue array with the desired mRowCount and mColumnCount
123  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
124  */
125  TTErr setDimensions(const TTValue& someNewDimensions);
126 
127  /** Alternative to attribute accessor. Set the values of mRowCount and mColumnCount with a TTInt32 vector (instead of using TTValue array). Values beyond the first two items in the vector will be ignored without an error. Values that are less than 1 will return an error. Support for N dimensions has been deprecated.
128  @param newDimensions a 2-item TTInt32 vector with the desired mRowCount and mColumnCount
129  @return TTErr kTTErrInvalidValue if value was outside allowed range, kTTErrAllocFailed if the resize operation could not be completed, otherwise kTTErrNone
130  */
131  TTErr setDimensionsWithVector(const std::vector<TTInt32>& newDimensions)
132  {
133  // NOTE: there is potential for some attributes to change while others fail
134  // if that happens, mData is never resized but attributes that changed will report bogus results
135 
136  if (this->setRowCountWithoutResize(newDimensions[0]) &&
137  this->setColumnCountWithoutResize(newDimensions[1]))
138  {
139  return resize();
140  } else {
141  return kTTErrInvalidValue;
142  }
143  }
144 
145  /** Simple data accessor.
146  @return TTRowID the value stored at mRowCount */
148  {
149  return mRowCount;
150  }
151 
152  /** Simple data accessor.
153  @return TTColumnID the value stored at mColumnCount */
155  {
156  return mColumnCount;
157  }
158 
159  /** Simple data accessor.
160  @return TTElementID the value stored at mElementCount */
162  {
163  return mElementCount;
164  }
165 
166  /** Simple data accessor.
167  @return TTUInt32 the value stored at mComponentCount */
169  {
170  return mComponentCount;
171  }
172 
173  /** Attribute accessor. Will set returnedType to a symbol matching the name of data type used in matrix.
174 
175  @param[out] returnedType a TValue with a symbol matching the name of data type
176  @return TTErr always returns kTTErrNone
177  */
178  TTErr getType(TTValue& returnedType) const;
179 
180  /** Simple data accessor.
181  @return TTDataType the value stored at mType */
183  {
184  return mType;
185  }
186 
187  /** Simple data accessor.
188  @return TTSymbolPtr the value stored at mTypeAsDataInfo->name */
190  {
191  return mTypeAsDataInfo->name;
192  }
193 
194  /** Simple data accessor.
195  @return TTDataInfoPtr the value stored at mTypeAsDataInfo*/
196  TTDataInfoPtr getTypeAsDataInfo()
197  {
198  return mTypeAsDataInfo;
199  }
200 
201  /** Simple data accessor.
202  @return TTUInt32 the value stored at mDataCount */
204  {
205  return mDataCount;
206  }
207 
208  /** Simple data accessor.
209  @return TTUInt32 the value stored at mComponentStride */
211  {
212  return mComponentStride;
213  }
214 
215  /** Legacy attribute accessor. Will set returnedDimensions as a 2-item TTValue using the values saved as RowCount & ColumnCount.
216 
217  @param[out] returnedDimensions a 2-item TTValue with mRowCount first & mColumnCount second
218  @return TTErr always returns kTTErrNone
219  */
220  TTErr getDimensions(TTValue& returnedDimensions) const;
221 
222 
223  /** Set every element in the matrix to zero.
224 
225  @return TTErr always returns kTTErrNone
226  */
227  TTErr clear();
228 
229  /** Fill every component in the matrix with the same value.
230 
231  @param[in] anInputValue TTValue array containing the elements used to fill matrix
232  @param[out] anOutputValue unused
233  @return TTErr always returns kTTErrNone
234  */
235  TTErr fill(const TTValue& anInputValue, TTValue &anOutputValue);
236 
237  //! [doxygenAppendixC_macroExample]
238  /** Internal macro used to locate the byte within mData where a specific component begins.
239  This macro is used by both get and set routines to ensure that the formula for access is consistent. Allows our interface to be consistent in its lookup method and represents a specific application of the <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY principle</a>.
240 
241  @param i row in matrix
242  @param j column in matrix
243 
244  @ingroup macros
245  */
246  #define INDEX_OF_COMPONENT_FIRSTBYTE(i, j) \
247  { \
248  (i * mColumnCount + j) * mComponentStride \
249  }
250  //! [doxygenAppendixC_macroExample]
251 
252 
253  /** Internal macro used to locate the byte within mData where a specific element begins.
254  This macro is used by both get and set routines to ensure that the formula for access is consistent. Allows our interface to be consistent in its lookup method and represents a specific application of the <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY principle</a>.
255 
256  @param i row in matrix
257  @param j column in matrix
258  @param e element within component
259 
260  @ingroup macros
261  */
262  #define INDEX_OF_ELEMENT_FIRSTBYTE(i, j, e) \
263  { \
264  (i * mColumnCount + j) * mComponentStride + e * mTypeSizeInBytes \
265  }
266 
267 
268  /** A function pointer for implementing handlers in the makeInBounds() method.
269  The format for this function pointer follows most of the methods defined in TTLimits (i.e. TTClip, TTInfWrap, TTFold) which means they can be used here to handle out of bounds values. However, the methods defined in this class (i.e. outOfBoundsClip, outOfBoundsWrap, outOfBoundsFold) are safer because they handle considerations specific to TTMatrixBase.
270 
271  @param[in] index reference to an index that will be checked and corrected if not in bounds
272  @param[in] lowBound lowest value allowed for index
273  @param[in] highBound highest value allowed for index
274  @return TTInt32 new index value that is within bounds
275 
276  @seealso TTLimits.h
277  */
278  typedef TTInt32 (*TTMatrixBaseOutOfBoundsHandler)(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound);
279 
280  /** In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTClip.
281  @seealso TTMatrixBaseOutOfBoundsHandler
282  */
283  static TTInt32 outOfBoundsClip(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
284  {
285  // the TTClip method does not depend highBound being equal to the dimension size, so we just subtract 1
286  return TTClip(index, lowBound, (highBound-1));
287  }
288 
289  /** In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTInfWrap.
290  @seealso TTMatrixBaseOutOfBoundsHandler
291  */
292  static TTInt32 outOfBoundsWrap(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
293  {
294  // the TTInfWrap method does not allow the highBound as a valid result, so we can pass values as is
295  TTInt32 temp = index;
296  TTInfWrap(temp, lowBound, highBound);
297  return temp;
298  }
299 
300  /** In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTFold.
301  @seealso TTMatrixBaseOutOfBoundsHandler
302  */
303  static TTInt32 outOfBoundsFold(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
304  {
305  // the TTFold method allows highBound as a valid result, but the math depends on it being equal to the dimension size
306  TTInt32 temp = index;
307  TTFold(temp, lowBound, highBound);
308  TTInt32 output = temp;
309  // so we adjust whenever highBound is produced as an output
310  if (output == highBound) --output;
311  return output;
312  }
313 
314  /** Make sure a TTRowID is within the limits set by RowCount.
315  This method can be used to force row values to fall within the defined limits of the TTMatrixBase.
316 
317  @param[in,out] i row in matrix of desired component
318  @param[in] handler function used to transform out of bounds values, outOfBoundsWrap is default if undefined
319  @return TTBoolean true if values changed, false if they remained constant
320  */
321  TTBoolean makeRowIDInBounds(TTRowID& i, TTMatrixBaseOutOfBoundsHandler handler = outOfBoundsWrap) const
322  {
323  TTRowID i_input = i;
324  i = (*handler)(i_input, TTRowID(0), mRowCount);
325  return (i_input != i); // true or false, did it change?
326  }
327 
328  /** Make sure a TTColumnID is within the limits set by ColumnCount.
329  This method can be used to force column values to fall within the defined limits of the TTMatrixBase.
330 
331  @param[in,out] j column in matrix of desired component
332  @param[in] handler function used to transform out of bounds values, outOfBoundsWrap is default if undefined
333  @return TTBoolean true if values changed, false if they remained constant
334  */
335  TTBoolean makeColumnIDInBounds(TTColumnID& j, TTMatrixBaseOutOfBoundsHandler handler = outOfBoundsWrap) const
336  {
337  TTColumnID j_input = j;
338  j = (*handler)(j_input, TTColumnID(0), mColumnCount);
339  return (j_input != j); // true or false, did it change?
340  }
341 
342  /** Make sure a TTElementID is within the limits set by ElementCount.
343  This method can be used to force element values to fall within the defined limits of the TTMatrixBase.
344 
345  @param[in,out] e element within desired component
346  @param[in] handler function used to transform out of bounds values, outOfBoundsWrap is default if undefined
347  @return TTBoolean true if values changed, false if they remained constant
348  */
349  TTBoolean makeElementIDInBounds(TTElementID& e, TTMatrixBaseOutOfBoundsHandler handler = outOfBoundsWrap) const
350  {
351  TTColumnID e_input = e;
352  e = (*handler)(e_input, TTElementID(0), mElementCount);
353  return (e_input != e); // true or false, did it change?
354  }
355 
356  /** Make sure an (i,j) pair is within the limits set by RowCount & ColumnCount.
357  This method can be used just before calls to the get or set methods and forces values to fall within the defined limits of the TTMatrixBase. This is simpler than checking the boundaries of (i,j) separately, but may be less efficient when one value is not changing as frequently as the other. It will also always use the same TTMatrixBaseOutOfBoundsHandler on all dimensions.
358 
359  @param[in,out] i row in matrix of desired component
360  @param[in,out] j column in matrix of desired component
361  @param[in] handler function used to transform out of bounds values, outOfBoundsWrap is default if undefined
362  @return TTBoolean true if values changed, false if they remained constant
363 
364  @seealso makeRowIDInBounds, makeColumnIDInBounds
365  */
366  TTBoolean makeInBounds(TTRowID& i, TTColumnID& j, TTMatrixBaseOutOfBoundsHandler handler = outOfBoundsWrap) const
367  {
368  TTUInt8 changes = 0; // keep track of how many changes are made
369  changes += makeRowIDInBounds(i, handler);
370  changes += makeColumnIDInBounds(j, handler);
371  return (changes > 0); // true or false, did anything change?
372  }
373 
374  /** Make sure an (i,j,e) set is within the limits set by RowCount, ColumnCount & ElementCount.
375  This method can be used just before calls to the get or set methods and forces values to fall within the defined limits of the TTMatrixBase. This is simpler than checking the boundaries of (i,j, e) separately, but may be less efficient when one value is not changing as frequently as the others. It will also always use the same TTMatrixBaseOutOfBoundsHandler on all dimensions.
376 
377  @param[in,out] i row in matrix of desired component
378  @param[in,out] j column in matrix of desired component
379  @param[in,out] e element within desired component
380  @param[in] handler function used to transform out of bounds values, outOfBoundsWrap is default if undefined
381  @return TTBoolean true if values changed, false if they remained constant
382 
383  @seealso makeRowIDInBounds, makeColumnIDInBounds, makeElementIDInBounds
384  */
385  TTBoolean makeInBounds(TTRowID& i, TTColumnID& j, TTElementID& e, TTMatrixBaseOutOfBoundsHandler handler = outOfBoundsWrap) const
386  {
387  TTUInt8 changes = 0; // keep track of how many changes are made
388  changes += makeRowIDInBounds(i, handler);
389  changes += makeColumnIDInBounds(j, handler);
390  changes += makeElementIDInBounds(e, handler);
391  return (changes > 0); // true or false, did anything change?
392  }
393 
394 
395  /** Get the value of a component located at any location in 2-dimensional matrix.
396  Pass in coordinate pair using anInputValue. Returns via anOutputValue an mElementCount-item TTValue using the values stored at the coordinates specified by anInputValue.
397  Remember that the first location in the matrix is row 0 and column 0.
398  Used primarily as an interface to the matrix data from Jamoma implementations in Ruby and Max. To retrieve values from the matrix with less overhead, see the get2d() method.
399 
400  @param[in] anInputValue TTValue array containing the row and column values of coordinates
401  @param[out] anOutputValue method sets to a TTValue array containing element(s) found at the given coordinates
402  @return TTErr kTTErrWrongNumValues if anInputValue does not have 2 items, else kTTErrNone
403  */
404  TTErr get(const TTValue& anInputValue, TTValue &anOutputValue) const;
405 
406 
407  /** Get the value of a component located at (i,j) in a 2-dimensional matrix.
408  Remember that the first component in the matrix is (0,0).
409 
410  In order to provide some degree of efficiency, the data passed-in is not bounds checked --
411  you must ensure that you are passing memory that is at least mComponentStride bytes large.
412 
413  In fact, you should pass a compound type if you want more than one of the primitive types.
414  For example, pass a pointer to a TTComplex if you want two doubles.
415 
416  @param[in] i row in matrix of desired component
417  @param[in] j column in matrix of desired component
418  @param[out] data reference to where method should return value
419  @return TTErr always returns kTTErrNone
420  */
421  template<typename T>
422  TTErr get2d(TTRowID i, TTColumnID j, T& data) const
423  {
425  //cout << "the size of your datatype is: " << sizeof(T) << "\n"; //test to prove that sizeof works on templates
426  data = *(T*)(mData + index);
427  return kTTErrNone;
428  }
429 
430 
431  /** Get the value of element e of the component located at (i,j) in a 2-dimensional matrix.
432  Remember that the first component in the matrix is (0,0) and its first element is 0.
433 
434  In order to provide some degree of efficiency, the data passed-in is not bounds checked --
435  you must ensure that you are passing memory that is at least mComponentStride bytes large.
436 
437  In fact, you should pass a compound type if you want more than one of the primitive types.
438  For example, pass a pointer to a TTComplex if you want two doubles.
439 
440  @param[in] i row in matrix of desired component
441  @param[in] j column in matrix of desired component
442  @param[in] e element within matrix component
443  @param[out] data reference to where method should return value
444  @return TTErr always returns kTTErrNone
445  */
446  template<typename T>
447  TTErr get2d(TTRowID i, TTColumnID j, TTElementID e, T& data) const
448  {
449  TTUInt32 index = INDEX_OF_ELEMENT_FIRSTBYTE(i, j, e);
450  data = *(T*)(mData + index);
451  return kTTErrNone;
452  }
453 
454 
455  /** Set the value of a component located at any location in an 2-dimensional matrix.
456  Pass in coordinate pair and new value using anInputValue. Returns nothing via anOutputValue.
457  Remember that the first location in the matrix is row 0 and column 0.
458  Used primarily as an interface to the matrix data from Jamoma implementations in Ruby and Max. To store values in the matrix with less overhead, see the set2d() method.
459 
460  @param[in] anInputValue TTValue array containing the row and column values of coordinates and elements to be stored at this location, therefore anInputValue requires (2 + mElementCount) items
461  @param[out] anOutputValue unused
462  @return TTErr kTTErrWrongNumValues if anInputValue does not have (2 + mElementCount) items, else kTTErrNone
463  */
464  TTErr set(const TTValue& anInputValue, TTValue &anOutputValue);
465 
466  /** Set the value of a component located at (i,j) in a 2-dimensional matrix.
467  Remember that the first component in the matrix is (0,0).
468 
469  In order to provide some degree of efficiency, the data passed-in is not bounds checked --
470  you must ensure that you are passing memory that is at least mComponentStride bytes large.
471 
472  In fact, you should pass a compound type if you want more than one of the primitive types.
473  For example, pass a pointer to a TTComplex if you want two doubles.
474 
475  @param[in] i row in matrix of component to be set
476  @param[in] j column in matrix of component to be set
477  @param[out] data reference to where method should return value
478  @return TTErr always returns kTTErrNone
479  */
480  template<typename T>
482  {
484  *(T*)(mData + index) = data;
485  return kTTErrNone;
486  }
487 
488  /** Set the value of element e of the component located at (i,j) in a 2-dimensional matrix.
489  Remember that the first component in the matrix is (0,0) and its first element is 0.
490 
491  In order to provide some degree of efficiency, the data passed-in is not bounds checked --
492  you must ensure that you are passing memory that is at least mComponentStride bytes large.
493 
494  In fact, you should pass a compound type if you want more than one of the primitive types.
495  For example, pass a pointer to a TTComplex if you want two doubles.
496 
497  @param[in] i row in matrix of component to be set
498  @param[in] j column in matrix of component to be set
499  @param[in] e element within matrix component
500  @param[out] data reference to where method should return value
501  @return TTErr always returns kTTErrNone
502  */
503  template<typename T>
505  {
506  TTUInt32 index = INDEX_OF_ELEMENT_FIRSTBYTE(i, j, e);
507  *(T*)(mData + index) = data;
508  return kTTErrNone;
509  }
510 
511 
512  /** You must proceed to set the various attributes, dimensions, etc. to match the data format of the matrix you are referencing.
513 
514  One caveat regards data alignment. Jitter, for example, aligns rows on 16-byte boundaries.
515  In this case, a 4x10 matrix (using the m-by-n convention rather than Jitter's width-by-height convention) of 32-bit ints,
516  all with a value of "4" will look like this:
517 
518  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0
519  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0
520  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0
521  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0
522 
523  Thus, the rows are really of a dimension length 12 instead of 10 and the total size of the matrix scales as well.
524 
525  For the time being, we do not handle this case.
526  Jitter users must dimension their matrices so that the row size in bytes is a multiple of 16.
527  This is not actually hard to do for most purposes. For example:
528 
529  float64, element count of 1, width is a multiple of 2 (an even number)
530  float32 or int32, element count of 1, width is a multiple of 4
531  uint8, element count of 1, width is a multiple of 16 (which includes 80, 160, 320, 640, ...), but
532  element count of 4 (i.e. color pixels) width should be a multiple of values.
533  */
534  void referenceExternalData(TTPtr aDataPointer)
535  {
536 
537  // TODO: see TTAudioSignal for more robust handling of freeing mData here, etc.
538  // TODO: see the destructor, because there is also the issue of refcounting the data references?
539  // for now we will just leak the memory until the design is complete
540  mDataIsLocallyOwned = NO;
541  mData = (TTBytePtr)aDataPointer;
542  }
543 
544 
545  /** Return a pointer to the matrix data, and lock the matrix so that others cannot access the data.
546  If matrix is already locked, this function waits until it becomes free. */
548  {
549  // TODO: actually lock the data and add spin-lock with atomic access
550  // NOTE: when locked, we cannot resize, change type, etc. either...
551 
552  return mData;
553  }
554 
555  /** Release a locked pointer obtained using getLockedPointer(). */
557  {
558  // TODO: see above.
559  // NOTE: we could also cache the pointer in getLockedPointer() and match it to this.
560  // But maybe that makes not sense.
561  }
562 
563 #if 0
564 #pragma mark -
565 #endif
566 
567 
568  /** Compare the attributes of this matrix to another to see if they all match. Used before conducting certain math operations.
569 
570  @param anotherMatrix matrix that you would like to compare to this one
571  @return TTBoolean true if mType, mElementCount, mRowCount AND mColumnCount match, otherwise false
572  */
573  TTBoolean allAttributesMatch(const TTMatrixBase& anotherMatrix) const;
574  TTBoolean allAttributesMatch(const TTMatrixBase* anotherMatrix) const
575  {
576  return TTMatrixBase::allAttributesMatch(*anotherMatrix);
577  }
578 
579  /** Copy the data from one matrix into another.
580 
581  @param[in] source matrix that you would like to copy FROM
582  @param[out] dest matrix that you would like to copy TO
583  @return TTErr kTTErrInvalidValue if operation is not completed, otherwise kTTErrNone
584  */
585  static TTErr copy(const TTMatrixBase& source, TTMatrixBase& dest);
586  static TTErr copy(const TTMatrixBase* source, TTMatrixBase* dest)
587  {
588  return TTMatrixBase::copy(*source, *dest);
589  }
590 
591  /** Set dimensions, element count, datatype, etc. (i.e. the metadata describing a matrix)
592  to match the another matrix which is passed-in as an argument.
593 
594  @param anotherMatrix matrix to which you would like to conform the attributes of this one
595  @return TTErr kTTErrInvalidValue if operation is not completed, otherwise kTTErrNone
596  */
597  TTErr adaptTo(const TTMatrixBase& anotherMatrix);
598  TTErr adaptTo(const TTMatrixBase* anotherMatrix)
599  {
600  return adaptTo(*anotherMatrix);
601  }
602 
603  /** A function pointer for implementing iterators used in the iterate() method.
604  @param[out] c pointer to matrix that holds the results of the operation
605  @param[in] a pointer to matrix 1 of 2 for the iteration operation
606  @param[in] b pointer to matrix 2 of 2 for the iteration operation
607  */
608  typedef void (*TTMatrixBaseIterator)(TTPtr c, const TTPtr a, const TTPtr b);
609 
610  /** Step through every component in the matrix A and B to produce matrix C using the specified iterator method.
611  @param[out] C pointer to matrix that holds the results of the operation
612  @param[in] A pointer to matrix 1 of 2 for the iteration operation
613  @param[in] B pointer to matrix 2 of 2 for the iteration operation
614  @param[in] iterator function that will be used to operate on matrices A and B
615  @return TTErr kTTErrGeneric if attributes do not match or if iterate fails, otherwise returns kTTErrNone
616  */
617  static TTErr iterate(TTMatrixBase* C, const TTMatrixBase* A, const TTMatrixBase* B, TTMatrixBaseIterator iterator);
618 
619  /** Only if all the attributes of matrix A and B match, then step through every component to produce matrix C using the specified iterator method.
620  @param[out] C pointer to matrix that holds the results of the operation
621  @param[in] A pointer to matrix 1 of 2 for the iteration operation
622  @param[in] B pointer to matrix 2 of 2 for the iteration operation
623  @param[in] iterator function that will be used to operate on matrices A and B
624  @return TTErr kTTErrGeneric if attributes do not match or if iterate fails, otherwise returns kTTErrNone
625  */
626  static TTErr iterateWhenAllAttributesMatch(TTMatrixBase* C, const TTMatrixBase* A, const TTMatrixBase* B, TTMatrixBaseIterator iterator);
627 
628  /** Add two matrices to produce a third matrix.
629  The resulting matrix is instantiated by this method.
630  You, the caller, are responsible for freeing it. */
631  TTMatrixBase* operator + (const TTMatrixBase& B) const;
632 
633  /** Subtract matrix B from matrix A to produce matrix C.
634  The resulting matrix is instantiated by this method.
635  You, the caller, are responsible for freeing it. */
636  TTMatrixBase* operator - (const TTMatrixBase& B) const;
637 
638 };
639 
640 
643 
644 //TTMatrixBasePtr operator + (const TTMatrixBase& A, const TTMatrixBase& B);
645 
646 
647 #define TTMATRIX_PROCESS_MATRICES_WITH_NAMED_TEMPLATE(template_name, input_matrix, output_matrix) \
648  if (input_matrix->getTypeAsDataType() == kTypeUInt8) \
649  err = template_name<TTUInt8>(input_matrix, output_matrix); \
650  else if (input_matrix->getTypeAsDataType() == kTypeInt32) \
651  err = template_name<TTInt32>(input_matrix, output_matrix); \
652  else if (input_matrix->getTypeAsDataType() == kTypeFloat32) \
653  err = template_name<TTFloat32>(input_matrix, output_matrix); \
654  else if (input_matrix->getTypeAsDataType() == kTypeFloat64) \
655  err = template_name<TTFloat64>(input_matrix, output_matrix); \
656  else \
657  err = kTTErrInvalidType;
658 
659 
660 #endif // __TT_MATRIX_BASE_H__
661 
TTErr get2d(TTRowID i, TTColumnID j, TTElementID e, T &data) const
Get the value of element e of the component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:447
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTErr setDimensionsWithVector(const std::vector< TTInt32 > &newDimensions)
Alternative to attribute accessor.
Definition: TTMatrixBase.h:131
TTBytePtr getLockedPointer()
Return a pointer to the matrix data, and lock the matrix so that others cannot access the data...
Definition: TTMatrixBase.h:547
An inappropriate value was specified for an attribute or variable.
Definition: TTBase.h:349
TTBoolean allAttributesMatch(const TTMatrixBase &anotherMatrix) const
Compare the attributes of this matrix to another to see if they all match.
Limiting and Constraining Utilities.
static TTInt32 outOfBoundsWrap(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTInfWrap.
Definition: TTMatrixBase.h:292
#define INDEX_OF_ELEMENT_FIRSTBYTE(i, j, e)
[doxygenAppendixC_macroExample]
Definition: TTMatrixBase.h:262
TTBoolean makeColumnIDInBounds(TTColumnID &j, TTMatrixBaseOutOfBoundsHandler handler=outOfBoundsWrap) const
Make sure a TTColumnID is within the limits set by ColumnCount.
Definition: TTMatrixBase.h:335
TTUInt32 getComponentCount()
Simple data accessor.
Definition: TTMatrixBase.h:168
TTBoolean makeInBounds(TTRowID &i, TTColumnID &j, TTElementID &e, TTMatrixBaseOutOfBoundsHandler handler=outOfBoundsWrap) const
Make sure an (i,j,e) set is within the limits set by RowCount, ColumnCount & ElementCount.
Definition: TTMatrixBase.h:385
TTUInt32 mDataCount
mComponentCount * mElementCount (e.g. total number of floats or ints in the matrix) ...
Definition: TTMatrixBase.h:52
TTUInt32 getDataCount()
Simple data accessor.
Definition: TTMatrixBase.h:203
TTBoolean makeInBounds(TTRowID &i, TTColumnID &j, TTMatrixBaseOutOfBoundsHandler handler=outOfBoundsWrap) const
Make sure an (i,j) pair is within the limits set by RowCount & ColumnCount.
Definition: TTMatrixBase.h:366
TTDataObjectBase is the base class for all data generating and processing objects.
TTColumnID getColumnCount()
Simple data accessor.
Definition: TTMatrixBase.h:154
TTUInt32 mComponentCount
mRowCount * mColumnCount
Definition: TTMatrixBase.h:50
static TTErr copy(const TTMatrixBase &source, TTMatrixBase &dest)
Copy the data from one matrix into another.
TTDataType
TTBlue Data Types Enumeration of data types used through out TTBlue, including the TTValue class and ...
Definition: TTBase.h:269
TTInt32 TTColumnID
Datatype for any number used to indicate a column index within the matrix.
Definition: TTBase.h:216
TTDataObjectBase is the base class for all data generating and processing objects.
TTDataInfoPtr mTypeAsDataInfo
pointer to info about the data type found in #TTBase::ttDataTypeInfo
Definition: TTMatrixBase.h:54
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object This is the same as calling setAttributeValue().
Definition: TTObjectBase.h:251
TTUInt32 getComponentStride()
Simple data accessor.
Definition: TTMatrixBase.h:210
TTErr get2d(TTRowID i, TTColumnID j, T &data) const
Get the value of a component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:422
TTInt32 TTRowID
Datatype for any number used to indicate a row index within a matrix.
Definition: TTBase.h:207
TTElementID getElementCount()
Simple data accessor.
Definition: TTMatrixBase.h:161
TTSymbol mTypeAsSymbol
symbol with data type name for the public interface
Definition: TTMatrixBase.h:55
TTUInt32 mDataSize
mTypeSizeInBytes * mDataCount
Definition: TTMatrixBase.h:57
TTDataInfoPtr getTypeAsDataInfo()
Simple data accessor.
Definition: TTMatrixBase.h:196
static TTInt32 outOfBoundsClip(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTClip.
Definition: TTMatrixBase.h:283
#define TTCLASS_SETUP(className)
TODO Doxygen: need more comments here.
Definition: TTFoundation.h:54
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
2-dimensional matrix of compound values with N elements each.
Definition: TTMatrixBase.h:41
TTRowID getRowCount()
Simple data accessor.
Definition: TTMatrixBase.h:147
#define INDEX_OF_COMPONENT_FIRSTBYTE(i, j)
[doxygenAppendixC_macroExample]
Definition: TTMatrixBase.h:246
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTRowID mRowCount
How many rows of values the matrix should have. Uses an signed 32-bit integer which provides a maximu...
Definition: TTMatrixBase.h:47
TTDataType getTypeAsDataType()
Simple data accessor.
Definition: TTMatrixBase.h:182
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
TTByte * TTBytePtr
Data is a pointer to some bytes.
Definition: TTBase.h:169
TTColumnID mColumnCount
How many columns of values the matrix should have. Uses an signed 32-bit integer which provides a max...
Definition: TTMatrixBase.h:48
void referenceExternalData(TTPtr aDataPointer)
You must proceed to set the various attributes, dimensions, etc.
Definition: TTMatrixBase.h:534
TTErr set2d(TTRowID i, TTColumnID j, T data)
Set the value of a component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:481
TTUInt8 mTypeSizeInBytes
number of bytes present in mType
Definition: TTMatrixBase.h:56
static TTInt32 outOfBoundsFold(const TTInt32 index, const TTInt32 lowBound, const TTInt32 highBound)
In implementation of the TTMatrixBaseOutOfBoundsHandler that wraps #TTFold.
Definition: TTMatrixBase.h:303
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTInt16 TTElementID
Datatype for any number used to indicate an element index within the matrix.
Definition: TTBase.h:224
void releaseLockedPointer()
Release a locked pointer obtained using getLockedPointer().
Definition: TTMatrixBase.h:556
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTSymbol getTypeAsSymbol()
Simple data accessor.
Definition: TTMatrixBase.h:189
TTErr set2d(TTRowID i, TTColumnID j, TTElementID e, T data)
Set the value of element e of the component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:504
No Error.
Definition: TTBase.h:343
TTBoolean makeElementIDInBounds(TTElementID &e, TTMatrixBaseOutOfBoundsHandler handler=outOfBoundsWrap) const
Make sure a TTElementID is within the limits set by ElementCount.
Definition: TTMatrixBase.h:349
TTUInt32 mComponentStride
how many bytes from one the beginning one matrix component to the next
Definition: TTMatrixBase.h:51
TTElementID mElementCount
How many elements (parts) per value (e.g. 2 for complex numbers, 4 for colors, default = 1)...
Definition: TTMatrixBase.h:49
virtual TTErr test(TTValue &)
[doxygenChapter60_virtualMethod]
TTBoolean mDataIsLocallyOwned
If false, then we are referencing outside memory which we don't own.
Definition: TTMatrixBase.h:58
TTDataType mType
member of global enumerated list #TTBase::TTDataType (i.e., kTypeUInt8, kTypeUInt16, kTypeInt32, kTypeUInt64, kTypeFloat32, kTypeFloat64)
Definition: TTMatrixBase.h:53
TTBytePtr mData
memory used to store matrix values
Definition: TTMatrixBase.h:46
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTBoolean makeRowIDInBounds(TTRowID &i, TTMatrixBaseOutOfBoundsHandler handler=outOfBoundsWrap) const
Make sure a TTRowID is within the limits set by RowCount.
Definition: TTMatrixBase.h:321
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174