{{{ #!cobra class MultiList """ This class provides a generic n-dimensional multi-list containing any other type. The shape of a MultiList is a list of ints specifying the length of each dimension. Dimensions are called axes. The count is the total number of elements in the ML. For efficiency reasons, the MultiList class avoids copying its underlying data as much as possible. A ML can be a read-only view that shares data with an owner ML. The view can have a different shape, count, and/or order of axes than its owner. One way to construct a view is to call ml.slice Methods that perform operation in place return "this" which allows for method chaining. For example, ml.permute(order).reshape(shape).transpose If you want to perform operations on a view instead of the owner, call ml.view.permute(order).reshape(shape).transpose MultiList supports indexing, for example element = ml[i,j,k] ml[i,j,k] = element There are plans to support syntactical multidimensional slicing, such as ml2 = ml[a:b, c:d] However, at the moment, you should use .slice instead Inspiration for MultiList comes from similar libraries such as Boost.MultiArray -- http://www.boost.org/doc/libs/1_50_0/libs/multi_array/doc/reference.html Numpy.Array -- http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html Ruby NArray -- http://narray.rubyforge.org/SPEC.en MATLAB -- http://www.mathworks.com/products/matlab/ For further discussion on MultiLists, see the forum http://cobra-language.com/forums/viewtopic.php?f=4&t=974 or browse the source http://cobra-language.com/trac/cobra/browser/cobra/trunk/Source/Cobra.Core/MultiList.cobra """ shared const maxCount = 2_100_000_000 (as int) const maxDimRank = 10_000_000 (as int) const minDimRank = 1 (as int) var _count as int var _data as T[] var _dimOrder as IList """ Maps the order of the axes stored internally to the external permuted order """ var _inverseDimOrder as IList var _isPermuted as bool var _isReadOnly as bool var _isReferred as bool """ If a referrer is GC'ed, _isReferred will still be true """ var _numDims as int var _owner as MultiList? var _ranges as IList> """ For readonly multilists (aka views), _ranges is the range of elements per axis included in the view. """ var _shape as IList """ Shape is the size of each axis in the view """ var _strides as IList """ A stride is the number of places in _data separating two adjacent elements of a particular axes. Elements are stored in row major order. for equation, see http://en.wikipedia.org/wiki/Row-major_order#Generalization_to_higher_dimensions A slice has the same strides as its owner """ var _viewCount as int? cue init(shape as vari int) cue init(shape as IList) """ Constructor for a multilists that "owns" its data """ cue init(original as MultiList, ranges as IList>) """ The readonly view constructor returned from a slice """ cue init(shape as IList, data as T*) """ Length of data can be less than the count but not more """ get count as int get isPermuted as bool get isReadOnly as bool get isReferred as bool get numDims as int get owner as MultiList? """ In ml2 = ml1.slice, ml1 is the owner and ml2 is a view """ get shape as IList get toList as IList get view as MultiList pro [indices as vari int] as T def clone """ Returns a shallow copy """ def enumerate def equals(obj as Object?) def equals(m as MultiList) """ Equal if shapes are the same, and elements are in the same order. Ignores .isReadOnly, .isPermuted, .isReferred """ def fill(data as T*) def fill(start as int, data as T*) """ Throw IndexOutOfRangeException if the length of data + start exceeds .count """ def getHashCode """ As a completely mutable object, MultiList does not support getHashCode """ def permute(order as IList) """ Permutes the axes in place """ def reshape(shape as IList) """ Same as reshape(shape, false, false) """ def reshape(shape as IList, noCopy as bool, unsafe as bool) """ Reshapes the axes in place, unsafe == true will reshape the MultiList even if isReferred == true and the count of the shape is different than .count Will cause a data copy if necessary. If a view is copied, it's owner will be nil and .isReadOnly will be false """ def slice(ranges as vari Pair) """ Returns a readonly view of the ML. If ranges are provided for the first few axes, then the remaining ranges default to the whole axis. ml.slice() to-do: implement syntactic slicing as a property. This method is a placeholder. """ def toString def transpose """ Reverses the order of axes in place """ }}}