Wiki
Version 3 (modified by jaegs, 6 years ago)

--

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<of int>
        """
        Maps the order of the axes stored internally to
        the external permuted order
        """
        
    var _inverseDimOrder as IList<of int>
 
    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<of T>?
 
    var _ranges as IList<of Pair<of int>>
        """
        For readonly multilists (aka views), _ranges is the range of elements per axis
        included in the view.
        """
        
    var _shape as IList<of int>
        """
        Shape is the size of each axis in the view
        """
        
    var _strides as IList<of int>
        """
        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<of int>)
        """
        Constructor for a multilists that "owns" its data
        """
        
    cue init(original as MultiList<of T>, ranges as IList<of Pair<of int>>)
        """
        The readonly view constructor returned from a slice
        """
        
    cue init(shape as IList<of int>, 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<of T>?
        """
        In ml2 = ml1.slice, ml1 is the owner
        and ml2 is a view
        """
        
    get shape as IList<of int>
 
    get toList as IList<of T>
 
    get view as MultiList<of T>
    
    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<of T>)
        """
        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<of int>)
        """
        Permutes the axes in place
        """
 
    def reshape(shape as IList<of int>)
        """
        Same as reshape(shape, false, false)
        """
        
    def reshape(shape as IList<of int>, 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<of int>)
        """
        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
        """