/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// Permission is hereby granted, free of charge, to any person obtaining a copy /// of this software and associated documentation files (the "Software"), to deal /// in the Software without restriction, including without limitation the rights to /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of /// the Software, and to permit persons to whom the Software is furnished to do /// so, subject to the following conditions: /// /// The above copyright notice and this permission notice shall be included in all /// copies or substantial portions of the Software. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.Serialization; using System.Runtime.CompilerServices; using ILNumerics.Misc; using ILNumerics.Data; using ILNumerics.Exceptions; using System.Linq.Expressions; namespace ILNumerics.Storage { /// /// The class realizes an internal storage wrapper for cell arrays. It takes care of value semantics for reference types. /// [Serializable] internal class ILCellStorage : ILDenseStorage { #region attributes bool m_fromImplicitCast = false; #endregion #region properties internal bool FromImplicitCast { get { return m_fromImplicitCast; } set { m_fromImplicitCast = value; } } #endregion #region Constructors /// /// create new cell storage /// /// countable array /// dimensions internal ILCellStorage(ILStorage[] system_array, ILSize dimensions) : base(system_array, dimensions) { DeepReferenceElements(); } internal ILCellStorage(ILBaseArray[] system_array, ILSize dimensions) : base(baseArray2Storages(system_array, dimensions.NumberOfElements), dimensions) { DeepReferenceElements(); } internal ILCellStorage(ILCountableArray countableArray, ILSize dimensions) : base(countableArray, dimensions) { DeepReferenceElements(); } internal ILCellStorage(ILSize dimensions) : base(dimensions) { } #endregion #region public interface /// /// replace array at specified location /// /// new scalar value for element /// indices of element to be altered, supports 'deep indexing' internal override void SetValueTyped(ILStorage value, params int[] indices) { //if (Object.ReferenceEquals(value, null) || value.Size.NumberOfElements == 0) // throw new ILArgumentException("cell removal is not supported for single integer indexing. value specified must not be null"); int mydimlen = Size.NumberOfDimensions; if (indices.Length <= mydimlen) { try { // address this ILCell ILStorage curVal = base.GetValueTyped(indices); if (curVal != null) curVal.Dispose(); } catch (IndexOutOfRangeException) { } catch (ILArgumentException) { // address outside range -> no need to dispose } finally { base.SetValueTyped(value == null ? null: value.Clone(), indices); } } else { if (value != null && value.Size.NumberOfElements > 1) throw new ILArgumentException("value given must be scalar or null"); // address element of an element of this ILCell int[] innerIndices = new int[indices.Length - mydimlen]; int i = 1, elIndex = indices[0]; for (; i < mydimlen; i++) elIndex += (Size.SequentialIndexDistance(i) * indices[i]); if (elIndex > Size.NumberOfElements) throw new ILArgumentException("index out of range"); for (int n = 0; i < indices.Length; i++) innerIndices[n++] = indices[i]; ILStorage innerElement = GetArrayForRead()[elIndex]; if (object.Equals(innerElement, null)) throw new ILArgumentException("No array found in cell at indices specified. Invalid deep indices given."); if (innerElement is ILCellStorage) { innerElement.SetValue(value, innerIndices); } else { if (value != null && value.Size.NumberOfElements != 1) throw new ILArgumentException("deep cell indexing requires the new value to be a scalar. Given: " + value.Size.ToString()); innerElement.SetValue(value != null ? value.GetValue(0) : null, innerIndices); } //if (innerElement is ILDenseStorage) { // send the _reference_ of value to inner storage (clone will be done at the end) // (innerElement as ILDenseStorage).SetValueTyped(value, innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else if (value is ILStorage && innerElement is ILStorage) { // (innerElement as ILStorage).SetValueTyped((value as ILStorage).GetValueTyped(0), innerIndices); //} else { // throw new ILArgumentTypeException("right side argument type is not valid in this context. the value must have the same type as the inner array addressed"); //} } } /// /// get element from this cell storage /// /// indices of element /// element internal override ILStorage GetValueTyped(params int[] indices) { int mydimlen = Size.NumberOfDimensions; if (indices.Length <= mydimlen) { // address this ILCell ILStorage element = base.GetValueTyped(indices); return (element != null) ? element.Clone() : null; } else { // address element of an element of this ILCell (deep addressing) int[] innerIndices = new int[indices.Length - mydimlen]; int i = 1, elIndex = indices[0]; for (; i < mydimlen; i++) elIndex += (Size.SequentialIndexDistance(i) * indices[i]); for (int n = 0; i < indices.Length; i++) innerIndices[n++] = indices[i]; ILStorage innerElement = base.GetValueTyped(elIndex); if (innerElement == null) throw new ILArgumentException("Deep indices out of range. The specified element does not exist."); return innerElement.GetValueAsStorage(innerIndices); } } internal override ILStorage GetValueAsStorage(params int[] innerIndices) { return GetValueTyped(innerIndices); } /// /// test if an element of the cell is an array of the given element type /// /// the array element type to check the cell element against /// position of the cell element to be tested /// true if the element found at the given position is an array of the element type , false otherwise /// The method is helpful in order to investigate the contents of a cell array. If you are not sure about the /// types of elements in the cell, this function can be used to make sure, elements are of the expected type before retrieving them as such. /// In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as /// typeparameter . That means, in order to find out, if the first cell element stores an array of int (ILArray<int>), /// one may use cell.IsTypeOf<int>(0) /// In order to test, if a cell element is of cell type, one can provide the type ILCell as type parameter: /// cell.IsTypeOf<ILCell>(0). Note the different semantic when checking for cell elements of type cell. Here we do not test for the /// element type but for the array type itself, ie. ILCell. The reason of this is: the type of elements of ILCell is /// an implementation detail and therefore hidden to the user. /// /// /// In the following example a ILCell of size 3x2 is created. It stores several array types, among which other cells are stored as elements of the outer cell. /// ILCell cell = ILMath.cell(new ILSize(3, 2) /// , "first element" /// , 2.0 /// , ILMath.cell(Math.PI, 100f) /// , ILMath.create<short>(1, 2, 3, 4, 5, 6) /// , new double[] {-1.4, -1.5, -1.6}); /// /// The cell is now: /// ILCell [3,2] /// <String> first element <Int16> [2,3,4,5,6] /// <Double> 2 ILCell [1,3] /// ILCell [2,1] (null) /// /// We test the element type of every element in the cell: /// /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf<string>(0)); /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf<double>(0)); /// /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf<double>(1)); /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf<ILCell>(2)); /// /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf<short>(0, 1)); /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf<ILCell>(1, 1)); /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf<double>(2, 1)); /// /// This gives the following output: /// /// cell[0,0] is element type 'string': True /// cell[0,0] is element type 'double': False /// cell[1,0] is element type 'double': True /// cell[2,0] is element type 'ILCell': True /// cell[0,1] is element type 'short': True /// cell[1,1] is element type 'ILCell': True /// cell[2,1] is element type 'double': False // element is null, IsTypeOf<> never gives true /// public bool IsTypeOf(params ILBaseArray[] position) { ILCellStorage cellStorage = (ILCellStorage)Subarray(position); try { if (cellStorage.Size.NumberOfElements == 1) { ILStorage innerStorage = cellStorage.GetValueTyped(0); try { if (typeof(T) == typeof(ILCell)) { return innerStorage is ILCellStorage; } return (innerStorage is ILStorage); } finally { if (innerStorage != null) { innerStorage.Dispose(); } } } else { throw new ILArgumentException("indices must define a scalar subarray range"); } } finally { cellStorage.Dispose(); } } /// /// gives clone of value addressed, supports deep index addressing /// /// /// internal override object GetValue(params int[] indices) { int mydimlen = Size.NumberOfDimensions; if (indices.Length <= mydimlen) { // address this ILCell ILStorage element = base.GetValueTyped(indices); return (element != null) ? element.Clone() : null; } else { // address element of an element of this ILCell (deep addressing) int[] innerIndices = new int[indices.Length - mydimlen]; int i = 1, elIndex = indices[0]; for (; i < mydimlen; i++) elIndex += (Size.SequentialIndexDistance(i) * indices[i]); for (int n = 0; i < indices.Length; i++) innerIndices[n++] = indices[i]; ILStorage innerElement = base.GetValueTyped(elIndex); if (innerElement == null) throw new ILArgumentException("Deep indices out of range. The specified element does not exist."); return innerElement.GetValue(innerIndices); } } /// /// get single element from cell storage, predefined element type /// /// predefined type /// location of element to return /// element /// if the element found is not of the specified type public T GetValue(params int[] indices) { object obj = GetValue(indices); if (obj is T) return (T)obj; else throw new ILArgumentException("the element at specified position is not of requested type or does not exist"); } /// /// Alter elements of this storage adressed by sequential indices /// /// array specifying the elements to be altered, sequential indexing /// ILBaseArray of the same type than this array, holding the new values. /// The number of elements of storage must match the /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The /// single value of 'values' is than used to set all elements addressed by 'indices'. /// For empty arrays, scalar or vectors, indices outside the current bounds for /// this array will expand this array to the size neccessary. /// For other arrays the sequential indices given must fit inside this arrays dimensions. public override void SetRange(ILBaseArray indices, ILDenseStorage values) { //if (object.Equals(indices,null)) // throw new ILArgumentException("indices given must not be null"); if (object.Equals(values, null)) throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended."); #region set full shortcut // if (indices is ILFullRange || object.Equals(indices, null)) { if (object.Equals(indices, null)) { int pos; ILStorage[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ILStorage val = values.GetValueTyped(0); while (pos-- > 0) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos] = val; } } else { if (values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); pos = 0; foreach (ILStorage val in values) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos++] = val; } } } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements && values.Size.NumberOfElements != 1) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); #endregion if (indices.IsEmpty) return; if (indices.Storage is ILDenseStorage< double>) { double maxIndex, minIndex; ILDenseStorage< double> indStorage = indices.Storage as ILDenseStorage< double>; indStorage.GetLimits(out minIndex, out maxIndex); if (minIndex < 0) throw new ILArgumentException("sequential indices can not be negative"); if ((int)maxIndex >= m_size.NumberOfElements) { // handle resize if (m_size.NumberOfDimensions == 2) { if (m_size.NumberOfElements <= 1) { // scalar or empty -> expand along 1 ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] > 1 && m_size[1] == 1) { ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] == 1 && m_size[1] > 1) { ExpandArray(new int[] { 1, (int)maxIndex + 1 }); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } ILStorage[] myArray = GetArrayForWrite(); double[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; int ind; if (values.Size.NumberOfElements == 1) { ILStorage scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; i++) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[ind] = scalarElement; } } else { ILStorage[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } #region HYCALPER AUTO GENERATED CODE /// /// Alter elements of this storage adressed by sequential indices /// /// array specifying the elements to be altered, sequential indexing /// ILBaseArray of the same type than this array, holding the new values. /// The number of elements of storage must match the /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The /// single value of 'values' is than used to set all elements addressed by 'indices'. /// For empty arrays, scalar or vectors, indices outside the current bounds for /// this array will expand this array to the size neccessary. /// For other arrays the sequential indices given must fit inside this arrays dimensions. public override void SetRange(ILBaseArray indices, ILDenseStorage values) { //if (object.Equals(indices,null)) // throw new ILArgumentException("indices given must not be null"); if (object.Equals(values, null)) throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended."); #region set full shortcut // if (indices is ILFullRange || object.Equals(indices, null)) { if (object.Equals(indices, null)) { int pos; ILStorage[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ILStorage val = values.GetValueTyped(0); while (pos-- > 0) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos] = val; } } else { if (values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); pos = 0; foreach (ILStorage val in values) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos++] = val; } } } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements && values.Size.NumberOfElements != 1) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); #endregion if (indices.IsEmpty) return; if (indices.Storage is ILDenseStorage< Int64>) { Int64 maxIndex, minIndex; ILDenseStorage< Int64> indStorage = indices.Storage as ILDenseStorage< Int64>; indStorage.GetLimits(out minIndex, out maxIndex); if (minIndex < 0) throw new ILArgumentException("sequential indices can not be negative"); if ((int)maxIndex >= m_size.NumberOfElements) { // handle resize if (m_size.NumberOfDimensions == 2) { if (m_size.NumberOfElements <= 1) { // scalar or empty -> expand along 1 ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] > 1 && m_size[1] == 1) { ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] == 1 && m_size[1] > 1) { ExpandArray(new int[] { 1, (int)maxIndex + 1 }); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } ILStorage[] myArray = GetArrayForWrite(); Int64[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; int ind; if (values.Size.NumberOfElements == 1) { ILStorage scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; i++) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[ind] = scalarElement; } } else { ILStorage[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } /// /// Alter elements of this storage adressed by sequential indices /// /// array specifying the elements to be altered, sequential indexing /// ILBaseArray of the same type than this array, holding the new values. /// The number of elements of storage must match the /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The /// single value of 'values' is than used to set all elements addressed by 'indices'. /// For empty arrays, scalar or vectors, indices outside the current bounds for /// this array will expand this array to the size neccessary. /// For other arrays the sequential indices given must fit inside this arrays dimensions. public override void SetRange(ILBaseArray indices, ILDenseStorage values) { //if (object.Equals(indices,null)) // throw new ILArgumentException("indices given must not be null"); if (object.Equals(values, null)) throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended."); #region set full shortcut // if (indices is ILFullRange || object.Equals(indices, null)) { if (object.Equals(indices, null)) { int pos; ILStorage[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ILStorage val = values.GetValueTyped(0); while (pos-- > 0) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos] = val; } } else { if (values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); pos = 0; foreach (ILStorage val in values) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos++] = val; } } } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements && values.Size.NumberOfElements != 1) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); #endregion if (indices.IsEmpty) return; if (indices.Storage is ILDenseStorage< Int32>) { Int32 maxIndex, minIndex; ILDenseStorage< Int32> indStorage = indices.Storage as ILDenseStorage< Int32>; indStorage.GetLimits(out minIndex, out maxIndex); if (minIndex < 0) throw new ILArgumentException("sequential indices can not be negative"); if ((int)maxIndex >= m_size.NumberOfElements) { // handle resize if (m_size.NumberOfDimensions == 2) { if (m_size.NumberOfElements <= 1) { // scalar or empty -> expand along 1 ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] > 1 && m_size[1] == 1) { ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] == 1 && m_size[1] > 1) { ExpandArray(new int[] { 1, (int)maxIndex + 1 }); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } ILStorage[] myArray = GetArrayForWrite(); Int32[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; int ind; if (values.Size.NumberOfElements == 1) { ILStorage scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; i++) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[ind] = scalarElement; } } else { ILStorage[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } /// /// Alter elements of this storage adressed by sequential indices /// /// array specifying the elements to be altered, sequential indexing /// ILBaseArray of the same type than this array, holding the new values. /// The number of elements of storage must match the /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The /// single value of 'values' is than used to set all elements addressed by 'indices'. /// For empty arrays, scalar or vectors, indices outside the current bounds for /// this array will expand this array to the size neccessary. /// For other arrays the sequential indices given must fit inside this arrays dimensions. public override void SetRange(ILBaseArray indices, ILDenseStorage values) { //if (object.Equals(indices,null)) // throw new ILArgumentException("indices given must not be null"); if (object.Equals(values, null)) throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended."); #region set full shortcut // if (indices is ILFullRange || object.Equals(indices, null)) { if (object.Equals(indices, null)) { int pos; ILStorage[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ILStorage val = values.GetValueTyped(0); while (pos-- > 0) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos] = val; } } else { if (values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); pos = 0; foreach (ILStorage val in values) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos++] = val; } } } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements && values.Size.NumberOfElements != 1) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); #endregion if (indices.IsEmpty) return; if (indices.Storage is ILDenseStorage< Int16>) { Int16 maxIndex, minIndex; ILDenseStorage< Int16> indStorage = indices.Storage as ILDenseStorage< Int16>; indStorage.GetLimits(out minIndex, out maxIndex); if (minIndex < 0) throw new ILArgumentException("sequential indices can not be negative"); if ((int)maxIndex >= m_size.NumberOfElements) { // handle resize if (m_size.NumberOfDimensions == 2) { if (m_size.NumberOfElements <= 1) { // scalar or empty -> expand along 1 ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] > 1 && m_size[1] == 1) { ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] == 1 && m_size[1] > 1) { ExpandArray(new int[] { 1, (int)maxIndex + 1 }); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } ILStorage[] myArray = GetArrayForWrite(); Int16[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; int ind; if (values.Size.NumberOfElements == 1) { ILStorage scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; i++) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[ind] = scalarElement; } } else { ILStorage[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } /// /// Alter elements of this storage adressed by sequential indices /// /// array specifying the elements to be altered, sequential indexing /// ILBaseArray of the same type than this array, holding the new values. /// The number of elements of storage must match the /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The /// single value of 'values' is than used to set all elements addressed by 'indices'. /// For empty arrays, scalar or vectors, indices outside the current bounds for /// this array will expand this array to the size neccessary. /// For other arrays the sequential indices given must fit inside this arrays dimensions. public override void SetRange(ILBaseArray indices, ILDenseStorage values) { //if (object.Equals(indices,null)) // throw new ILArgumentException("indices given must not be null"); if (object.Equals(values, null)) throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended."); #region set full shortcut // if (indices is ILFullRange || object.Equals(indices, null)) { if (object.Equals(indices, null)) { int pos; ILStorage[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ILStorage val = values.GetValueTyped(0); while (pos-- > 0) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos] = val; } } else { if (values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); pos = 0; foreach (ILStorage val in values) { if (myArray[pos] != null) myArray[pos].Dispose(); myArray[pos++] = val; } } } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements && values.Size.NumberOfElements != 1) throw new ILArgumentException("number of elements in source must match number of elements in destination array"); #endregion if (indices.IsEmpty) return; if (indices.Storage is ILDenseStorage< float>) { float maxIndex, minIndex; ILDenseStorage< float> indStorage = indices.Storage as ILDenseStorage< float>; indStorage.GetLimits(out minIndex, out maxIndex); if (minIndex < 0) throw new ILArgumentException("sequential indices can not be negative"); if ((int)maxIndex >= m_size.NumberOfElements) { // handle resize if (m_size.NumberOfDimensions == 2) { if (m_size.NumberOfElements <= 1) { // scalar or empty -> expand along 1 ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] > 1 && m_size[1] == 1) { ExpandArray(new int[] { (int)maxIndex + 1, 1 }); } else if (m_size[0] == 1 && m_size[1] > 1) { ExpandArray(new int[] { 1, (int)maxIndex + 1 }); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } else throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only"); } ILStorage[] myArray = GetArrayForWrite(); float[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; int ind; if (values.Size.NumberOfElements == 1) { ILStorage scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; i++) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[ind] = scalarElement; } } else { ILStorage[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { ind = (int)indArray[i]; if (myArray[ind] != null) myArray[ind].Dispose(); myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } #endregion HYCALPER AUTO GENERATED CODE internal override void SetRangeFull(ILDenseStorage values) { if (values.Size.NumberOfElements != 1 && values.Size.NumberOfElements != Size.NumberOfElements) throw new ILArgumentException("source and destination array must have the same number of arguments"); ILStorage[] myArr = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { ILStorage scal = values.GetValueTyped(0); for (int i = Size.NumberOfElements; i-- > 0; ) { if (myArr[i] != null) myArr[i].Dispose(); myArr[i] = scal; } } else { ILStorage[] valArr = values.GetArrayForRead(); for (int i = Size.NumberOfElements; i-- > 0; ) { if (myArr[i] != null) myArr[i].Dispose(); myArr[i] = valArr[i]; } } } public override void SetRange(ILRange range, ILDenseStorage values) { if (range.Size.NumberOfElements == 0) return; int rangeDimLen = range.RangeArray.Length, higherDimSum = 0; int leadDimLenRange = range[0].Count, leadDimLen = m_size[0]; int d, outElemCount = range.Size.NumberOfElements; ILStorage[] myArr = GetArrayForWrite(); int[] idxArr = new int[rangeDimLen]; // used to store current position inside higher dims ILIntList[] rng = range.RangeArray; int[] seqDistances = m_size.GetSequentialIndexDistances(range.Size.NumberOfDimensions); int[] inFullDim = new int[rangeDimLen]; // initialize higher dimension summand and inFullDim[] flag array for (int i = 1; i < idxArr.Length; i++) { if (rng[i][0] < 0) { inFullDim[i] = rng[i][0]; } else { inFullDim[i] = 0; higherDimSum += seqDistances[i] * rng[i][0]; } } //for (int lIdx = 0; lIdx < leadDimLenRange; lIdx ++) { // retArr[curPosOut++] = myArr[higherDimSum + rleadDim[lIdx]]; //} if (values.Size.NumberOfElements == 1) { #region scalar case ILStorage scalar = values.GetValueTyped(0); while (true) { #region copy along leading dimension for (int i = 0; i < rng[0].Count; i++) { if (rng[0][i] < 0) { for (int c = -rng[0][i]; c-- >= 0; ) { ILStorage cur = myArr[higherDimSum]; if (cur != null) cur.Dispose(); myArr[higherDimSum] = scalar.Clone(); higherDimSum++; } higherDimSum += (rng[0][i] - 1); // negative value in rng! } else { int ind = higherDimSum + rng[0][i]; ILStorage cur = myArr[ind]; if (cur != null) cur.Dispose(); myArr[ind] = scalar.Clone(); } } #endregion #region increase higher dims d = 1; while (d < idxArr.Length) { if (inFullDim[d] < 0) { higherDimSum += seqDistances[d]; inFullDim[d]++; break; } if (rng[d][idxArr[d]] >= 0) { higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]); } else { higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]); } idxArr[d]++; if (idxArr[d] == rng[d].Count) { idxArr[d] = 0; if (rng[d][idxArr[d]] < 0) { inFullDim[d] = rng[d][idxArr[d]]; } d++; } else if (rng[d][idxArr[d]] < 0) { inFullDim[d] = rng[d][idxArr[d]]; break; } else { higherDimSum += seqDistances[d] * rng[d][idxArr[d]]; break; } } #endregion if (d >= idxArr.Length) break; } scalar.Dispose(); // we have only made copies of scalar input #endregion } else { #region non scalar case ILStorage[] valuesArr = values.GetArrayForRead(); int valuesPos = 0; while (true) { // copy along leading dimension for (int i = 0; i < rng[0].Count; i++) { if (rng[0][i] < 0) { for (int c = -rng[0][i]; c-- >= 0; ) { ILStorage cur = myArr[higherDimSum]; if (cur != null) cur.Dispose(); myArr[higherDimSum] = valuesArr[valuesPos]; valuesPos++; higherDimSum++; } higherDimSum += (rng[0][i] - 1); // negative value in rng! } else { int ind = higherDimSum + rng[0][i]; ILStorage cur = myArr[ind]; if (cur != null) cur.Dispose(); myArr[ind] = valuesArr[valuesPos]; valuesPos++; } } // increase higher dims d = 1; while (d < idxArr.Length) { if (inFullDim[d] < 0) { higherDimSum += seqDistances[d]; inFullDim[d]++; break; } if (rng[d][idxArr[d]] >= 0) { higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]); } else { higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]); } idxArr[d]++; if (idxArr[d] == rng[d].Count) { idxArr[d] = 0; if (rng[d][idxArr[d]] < 0) { inFullDim[d] = rng[d][idxArr[d]]; } d++; } else if (rng[d][idxArr[d]] < 0) { inFullDim[d] = rng[d][idxArr[d]]; break; } else { higherDimSum += seqDistances[d] * rng[d][idxArr[d]]; break; } } if (d >= idxArr.Length) break; } #endregion } } /// /// detach this storage: copy its countable array if needed /// protected override void Detach() { if (m_data.ReferenceCount <= 1) return; Data = m_data.CreateCopy(); } /// /// walk all elements of this cell and recursively replace them with clones of themself /// /// Due to the cloning mechanism of ILNumerics, the full clone /// will be cheap by using lazy copies of the data. Cloned elements will automatically be detached on write access. internal void DeepReferenceElements() { int len = Size.NumberOfElements; ILStorage[] myArr = GetArrayForWrite(); for (int i = 0; i < len; i++) { ILStorage a = myArr[i]; if (!Object.ReferenceEquals(a, null) && !a.IsDisposed) { ILStorage clone = a.Clone(); myArr[i] =clone; } else myArr[i] = null; } } internal ILDenseStorage GetDenseStorage(params ILBaseArray[] indices) { ILCellStorage retStorage = (ILCellStorage)Subarray(indices); if (retStorage.Size.NumberOfElements == 1) { ILStorage innerStorage = (retStorage as ILCellStorage).GetValueTyped(0); if (innerStorage is ILDenseStorage) { return innerStorage as ILDenseStorage; } else { if (innerStorage == null) { throw new ILArgumentException("the type of the element at the specified position could not be determined"); } Type innerStorageType = innerStorage.GetType(); if (innerStorageType == typeof(ILCellStorage)) throw new ILArgumentException("The cell element specified contains a cell storage. Use GetCell() in order to retrieve cells from cells!"); if (!innerStorageType.Name.Contains("ILDenseStorage")) // unlikely to happen in ILNumerics R2 throw new ILArgumentException("the type of the element at the specified position is not valid in this context"); Type[] arguments = innerStorageType.GetGenericArguments(); if (arguments.Length > 0) throw new ILArgumentException(String.Format("the array found at the specified location is of type <{0}> and not of the requested type <{1}>",arguments[0].Name, typeof(T).Name)); throw new ILArgumentException("an unknown error occoured while trying to retrieve the cell element"); } } else { throw new ILArgumentException("indices must define a scalar subarray range to an existing cell element"); } } internal ILBaseArray GetScalar(params ILBaseArray[] indices) { ILCellStorage cellStorage = (ILCellStorage)Subarray(indices); if (cellStorage.Size.NumberOfElements == 1) { ILStorage innerStorage = cellStorage.GetValueTyped(0); return (innerStorage == null) ? null : innerStorage.GetAsBaseArray(); } else { throw new ILArgumentException("indices must define a scalar subarray range"); } } internal override ILBaseArray GetAsBaseArray() { return new ILRetCell((ILCellStorage)Clone()); } internal override void Dispose(bool manual) { if (IsDisposed) return; for (int i = m_size.NumberOfElements; i--> 0;) { ILStorage storage = m_data.Data[i]; if(storage != null) storage.Dispose(manual); } base.Dispose(manual); } internal override bool Equals(object obj) { if (object.Equals(obj, null)) return false; ILCellStorage obStor = obj as ILCellStorage; if (obStor != null) { if (!obStor.Size.IsSameSize(Size)) return false; ILStorage[] myArr = GetArrayForRead(); ILStorage[] objArr = obStor.GetArrayForRead(); for (int i = Size.NumberOfElements; i --> 0; ) { ILStorage stor1 = myArr[i]; ILStorage stor2 = objArr[i]; if (stor1 == null ^ stor2 == null) return false; if (stor1 == null) continue; if (!myArr[i].Equals(objArr[i])) return false; } return true; } else { return false; } } #endregion #region helper private static ILStorage[] baseArray2Storages(ILBaseArray[] system_array, int minLength) { using (ILScope.Enter(system_array)) { ILStorage[] ret = ILMemoryPool.Pool.New(minLength); int i = 0; for (; i < system_array.Length; i++) { ILBaseArray curArr = system_array[i]; if (curArr == null) { ret[i] = null; } else { ILStorage cur = system_array[i].Storage; ret[i] = cur; } } // clear the rest of the array for (; i < minLength; i++) ret[i] = null; return ret; } } protected override ILDenseStorage CreateSelf(ILStorage[] data, ILSize size) { ILCellStorage ret = new ILCellStorage(data, size); //ret.DeepReferenceElements(); return ret; } protected override ILDenseStorage CreateSelf(ILSize size) { ILCellStorage ret = new ILCellStorage(size); //ret.DeepReferenceElements(); return ret; } protected override ILDenseStorage CreateSelf(ILCountableArray Data, ILSize ILSize) { ILCellStorage ret = new ILCellStorage(Data, ILSize); //ret.DeepReferenceElements(); return ret; } internal override string ShortInfo() { if (IsDisposed) return "Cell (disposed)"; return "Cell " + Size.ToString(); } //internal override void Remove(int dimension, ILIntList indices) { // using (ILScope.Enter()) { // if (dimension >= Dimensions.NumberOfDimensions) // throw new ILArgumentException("index out of range"); // if (dimension == -1) { // Data = new ILCountableArray(0); // m_dimensions = ILSize.Empty00; // return; // } // // TODO: may should be replaced with a faster (&fancier? ) version... ?? // ILBaseArray[] dims = new ILBaseArray[Dimensions.NumberOfDimensions]; // ILIntList keepInd = ILIntList.Create(); // ILIntList remvInd = indices; // int max = Dimensions[dimension]; // foreach (int i in indices) // if (i >= max || i < 0) throw new ILArgumentException("removal index out of range"); // for (int i = 0; i < max; i++) { // if (!remvInd.Contains(i)) { // keepInd.Add(i); // } // } // // we give the indices to _keep_ to the subarray function // ILArray remIndices = ILMath.create(keepInd.GetArray(), new ILSize(1, keepInd.Count)); // if (remIndices.Dimensions.NumberOfElements == Dimensions[dimension]) { // // nothing to do // return; // } // for (int i = 0; i < dims.Length; i++) { // dims[i] = ILMath.full; // } // dims[dimension] = remIndices; // ILCellStorage ret = (ILCellStorage)Subarray(dims); // //ret.DeepReferenceElements(); // Dispose(); // Data = ret.Data; // m_dimensions = ret.Dimensions; // } //} #endregion } }