/// /// 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 System.Numerics; using ILNumerics.Misc; using ILNumerics.Data; using ILNumerics.Exceptions; using System.Linq.Expressions; namespace ILNumerics.Storage { /// /// The class realizes an internal storage wrapper. It stores the internal data array /// and the dimension specifications for both: ILRetArray and ILDenseStorage (reference and solid). /// [System.Diagnostics.DebuggerTypeProxy(typeof(ILNumerics.Misc.ILArrayDebuggerProxy<>))] [System.Diagnostics.DebuggerDisplay("{ShortInfo(),nq}")] [Serializable] internal partial class ILDenseStorage : ILStorage { #region attributes /// /// Internal storage object. Contains the final System.Array storage and a reference counter. /// [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] protected ILCountableArray m_data; #endregion #region properties /// /// number of storages referencing the current data array /// internal int ReferenceCount { get { return m_data.ReferenceCount; } } /// /// Determine, if this storage has already been disposed. /// internal override bool IsDisposed { get { return m_data == null; } } protected ILCountableArray Data { get { return m_data; } set { ILCountableArray old = m_data; m_data = value; m_data.IncreaseReference(); if (old != null) old.DecreaseReference(); } } /// /// Get minimum and maximum value of all elements - if these exist. /// /// Output: minimum value. /// Output: maximum value. /// True if the limits exists and could be computed, false otherwise. /// Empty arrays will return false. The output parameter will be default(type). internal override bool GetLimits(out ElementType minValue, out ElementType maxValue) { return GetLimits(out minValue, out maxValue, true); } /// /// Get minimum and maximum value of all elements - if existing /// /// Output: minimum value. /// Output: maximum value. /// true: recognize Inf, NaN values; false: ignore those values /// True if the limits exists and could be computed, false otherwise. /// Empty arrays will return false. The output parameter will be default(ElementType) then. internal override bool GetLimits(out ElementType minValue, out ElementType maxValue, bool includeInfNaNs) { minValue = default(ElementType); maxValue = default(ElementType); if (m_size.NumberOfElements == 0) return false; if (false) { } else if (this is ILDenseStorage ) { double [] data = ( double [])(object) GetArrayForRead(); double curVal; double curMin = Double.PositiveInfinity ; double curMax = Double.NegativeInfinity ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (double.IsInfinity(curVal)) continue; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > Double.NegativeInfinity || curMin < Double.PositiveInfinity ); #region HYCALPER AUTO GENERATED CODE } else if (this is ILDenseStorage ) { fcomplex [] data = ( fcomplex [])(object) GetArrayForRead(); fcomplex curVal; fcomplex curMin = new fcomplex(float.PositiveInfinity,float.PositiveInfinity) ; fcomplex curMax = new fcomplex(float.NegativeInfinity,float.NegativeInfinity) ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (fcomplex.IsInfinity(curVal)) continue; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > new fcomplex(float.NegativeInfinity,float.NegativeInfinity) || curMin < new fcomplex(float.NegativeInfinity,float.NegativeInfinity) ); } else if (this is ILDenseStorage ) { complex [] data = ( complex [])(object) GetArrayForRead(); complex curVal; complex curMin = new complex(Double.PositiveInfinity,Double.PositiveInfinity) ; complex curMax = new complex(Double.NegativeInfinity,Double.NegativeInfinity) ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (complex.IsInfinity(curVal)) continue; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > new complex(Double.NegativeInfinity,Double.NegativeInfinity) || curMin < new complex(Double.NegativeInfinity,Double.NegativeInfinity) ); } else if (this is ILDenseStorage ) { byte [] data = ( byte [])(object) GetArrayForRead(); byte curVal; byte curMin = Byte.MaxValue ; byte curMax = Byte.MinValue ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > Byte.MinValue || curMin < Byte.MinValue ); } else if (this is ILDenseStorage ) { Int64 [] data = ( Int64 [])(object) GetArrayForRead(); Int64 curVal; Int64 curMin = Int64.MaxValue ; Int64 curMax = Int64.MinValue ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > Int64.MinValue || curMin < Int64.MinValue ); } else if (this is ILDenseStorage ) { Int32 [] data = ( Int32 [])(object) GetArrayForRead(); Int32 curVal; Int32 curMin = Int32.MaxValue ; Int32 curMax = Int32.MinValue ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > Int32.MinValue || curMin < Int32.MinValue ); } else if (this is ILDenseStorage ) { float [] data = ( float [])(object) GetArrayForRead(); float curVal; float curMin = float.PositiveInfinity ; float curMax = float.NegativeInfinity ; int curMinInd = 0; int curMaxInd = 0; int len = m_size.NumberOfElements; for (int i = 0; i < len; i++) { curVal = data[i]; if(float.IsInfinity(curVal)) continue; if (curVal < curMin) { curMin = curVal; curMinInd = i; } if (curVal > curMax) { curMax = curVal; curMaxInd = i; } } maxValue = m_data.Data[curMaxInd]; minValue = m_data.Data[curMinInd]; return (curMax > float.NegativeInfinity || curMin < float.NegativeInfinity ); #endregion HYCALPER AUTO GENERATED CODE } else if ((typeof(ElementType) is IComparable)) { ElementType[] tmpArr = GetArrayForRead(); for (int i = 0; i < m_size.NumberOfElements; i++) { ElementType val = tmpArr[i]; if (((IComparable)val).CompareTo(minValue) < 0) minValue = val; if (((IComparable)val).CompareTo(minValue) > 0) maxValue = val; } return true; } return false; } #endregion #region overriding object.ToString(), Equals() /// /// Write information about the ILDenseStorage to string. /// /// String containing general information about the current instance of /// ILDenseStorage and the formatted elements' values. /// If the number of elements exceeds a certain amount, the display will be abreviated. public override string ToString() { return ValuesToString(0).ToString(); } /// /// print formated values to string /// /// Maximum number of characters per line. 0: no limit /// StringBuilder object filled with formated values. internal override StringBuilder ValuesToString(int maxLength) { StringBuilder s = new StringBuilder(); if (maxLength <= 0) maxLength = int.MaxValue; //if (m_dimensions.NumberOfElements > 100000) { // s.Append(String.Format("({0})", m_dimensions.ToString())); // return s; //} if (m_size.NumberOfElements < 1) return new StringBuilder("(Empty)"); int[] acc = new int[m_size.NumberOfDimensions]; int d; String sElement; int elemLength = 10; //string format = "{0,20: E13;-E13; 0.0 } "; int curLineLength = 0, curRowsCount = 0; int maxRows = (maxLength == int.MaxValue) ? int.MaxValue : 500; // limit data rows in debugger view if (false) { } else if (this.Data.Data.GetType() == typeof( double [] )) { #region double element; double [] elements = (this.Data.Data as double []); elemLength = 10 ; double scaling = getScalingForPrint(); elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ((scaling == 1 && (int)element == element) ? "{0} " : "{0:f5} ", element / scaling).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion #region HYCALPER AUTO GENERATED CODE } else if (this.Data.Data.GetType() == typeof( float [] )) { #region float element; float [] elements = (this.Data.Data as float []); elemLength = 5 ; float scaling = (float)getScalingForPrint(); elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0:f5} ", element / scaling).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( fcomplex [] )) { #region fcomplex element; fcomplex [] elements = (this.Data.Data as fcomplex []); elemLength = 24 ; float scaling = (float)getScalingForPrint(); elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0} ", (element / scaling).ToString(5)).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( complex [] )) { #region complex element; complex [] elements = (this.Data.Data as complex []); elemLength = 36 ; double scaling = getScalingForPrint(); elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0} ", (element / scaling).ToString(5)).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( Complex [] )) { #region Complex element; Complex [] elements = (this.Data.Data as Complex []); elemLength = 36 ; double scaling = getScalingForPrint(); elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0} ", ComplexHelper(element / scaling,5)).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( byte [] )) { #region byte element; byte [] elements = (this.Data.Data as byte []); elemLength = 3 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,3:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( char [] )) { #region char element; char [] elements = (this.Data.Data as char []); elemLength = 3 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,3:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( UInt64 [] )) { #region UInt64 element; UInt64 [] elements = (this.Data.Data as UInt64 []); elemLength = 18 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,18:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( UInt32 [] )) { #region UInt32 element; UInt32 [] elements = (this.Data.Data as UInt32 []); elemLength = 10 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,10:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( UInt16 [] )) { #region UInt16 element; UInt16 [] elements = (this.Data.Data as UInt16 []); elemLength = 5 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,5:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( Int64 [] )) { #region Int64 element; Int64 [] elements = (this.Data.Data as Int64 []); elemLength = 18 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,18:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( Int32 [] )) { #region Int32 element; Int32 [] elements = (this.Data.Data as Int32 []); elemLength = 10 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,10:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( Int16 [] )) { #region Int16 element; Int16 [] elements = (this.Data.Data as Int16 []); elemLength = 5 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0,5:G} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( ILStorage [] )) { #region ILStorage element; ILStorage [] elements = (this.Data.Data as ILStorage []); elemLength = 0 ; double scaling = 1.0; for (int i = 0; i < m_size.NumberOfElements; i++) { element = elements[i]; int l = (element == null)? 6 : element.ShortInfo().Length; if (l > elemLength) elemLength = l; } elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = element.ShortInfo().PadRight(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else if (this.Data.Data.GetType() == typeof( object [] )) { #region object element; object [] elements = (this.Data.Data as object []); elemLength = 18 ; double scaling = 1.0; elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2 || scaling != 1) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):"")); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements [m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element,null)) { sElement = String.Format ("{0} ", element).PadLeft(elemLength); } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion #endregion HYCALPER AUTO GENERATED CODE } else if (this is ILDenseStorage ) { #region string element; string[] elements = (this.Data.Data as string[]); elemLength = 18; int maxElemLength = 50; // todo: may better be a setting? abreviate after as many chars elemLength++; while (acc[m_size.NumberOfDimensions - 1] < m_size[m_size.NumberOfDimensions - 1]) { // show only two first dimensions at the same time ... // print header if (m_size.NumberOfDimensions > 2) { if (s.Length > 0) s.Append(Environment.NewLine); s.Append("(:,:"); for (d = 2; d < m_size.NumberOfDimensions; d++) s.Append(String.Format(",{0}", acc[d])); s.Append(") "); } // show this for 2 leading dimensions for (int d0 = 0; d0 < m_size[0]; d0++) { if (++curRowsCount > maxRows) { s.Append(Environment.NewLine + "( ... more rows exist)"); return s; } if (s.Length > 0) s.Append(Environment.NewLine); acc[0] = d0; curLineLength = 0; for (int d1 = 0; d1 < m_size[1]; d1++) { acc[1] = d1; element = elements[m_size.IndexFromArray(acc)]; if (!Object.ReferenceEquals(element, null)) { if (element.Length > maxElemLength) { sElement = element.Substring(0,maxElemLength - 3) + "..."; } else { sElement = String.Format("{0} ", element).PadLeft(elemLength); } } else { sElement = "(null)".PadLeft(elemLength); } curLineLength += sElement.Length; if (curLineLength > maxLength - " ...".Length) { s.Append(" ..."); break; } else { s.Append(sElement); } } } // increase higher dimension d = 2; while (d <= m_size.NumberOfDimensions - 1) { acc[d]++; if (acc[d] < m_size[d]) break; acc[d] = 0; d++; } if (d >= m_size.NumberOfDimensions) break; } #endregion } else { return new StringBuilder ("(Unknown data type.)"); } return s; } private double getScalingForPrint() { ElementType min, max; if (GetLimits(out min, out max, false)) { try { double scaling = Math.Max( Math.Abs(double.Parse(min.ToString())), Math.Abs( double.Parse(max.ToString())) ); if (scaling == 0 || (scaling > 1e-1 && scaling < 1e1)) scaling = 1; scaling = Math.Pow(10,Math.Floor(Math.Log10(scaling))); if (scaling < 10000 && scaling >= 1) scaling = 1; return scaling; } catch (Exception) { return 1.0; } } else { return 1.0; } } private int GetTypedElementStringProperties(double scaling, out string format) { format = "E+00000000000000;0.0;-E+00000000000000"; if (this is ILDenseStorage) { return double.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return float.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return double.MaxValue.ToString().Length * 2 + 2; } else if (this is ILDenseStorage) { return double.MaxValue.ToString().Length * 2 + 2; } else if (this is ILDenseStorage) { return float.MaxValue.ToString().Length * 2 + 2; } else if (this is ILDenseStorage) { return char.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return byte.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return Int16.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return Int32.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return Int64.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return UInt16.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return UInt32.MaxValue.ToString().Length; } else if (this is ILDenseStorage) { return UInt64.MaxValue.ToString().Length; } else return 10; } private string ComplexHelper(Complex a, int digits) { if (digits < 1) return ""; if (a.Imaginary >= 0) { return String.Format("{0:f10}+{1:f10}", a.Real, a.Imaginary); } else { return String.Format("{0:f10}-{1:f10}", a.Real, -a.Imaginary); } } /// /// Check if the content of this array equals the content of obj. /// /// storage containing the values with which to compare this array. /// True if all elements contained in obj are equal to the /// elements of this array, false otherwise. /// This method compares the object references of corresponding elements. /// The size and type of both arrays must match. Otherwise false will be returned. internal override bool Equals(object obj) { if (object.Equals(obj,null)) return false; if (obj is ElementType) if (Size.NumberOfElements == 1 && obj.ToString() == GetValueTyped(0).ToString()) return true; else return false; ILDenseStorage denseStorage = obj as ILDenseStorage; if (object.Equals(denseStorage,null)) return false; return Equals(denseStorage); } /// /// Test if this dense storage equals another dense storage. /// /// storage to compare this storage with /// True if all elements and dimension sizes match, false otherwise. internal bool Equals(ILDenseStorage A) { if (A == null) return false; if (!A.Size.IsSameSize(m_size)) return false; int len = m_size.NumberOfElements; if (typeof(ElementType).IsValueType) { for (int i = 0; i < len;i++) { if (!GetValueTyped(i).Equals(A.GetValueTyped(i))) return false; } } else { // references may contain null element values! for (int i = 0; i < len;i++) { ElementType t1 = GetValueTyped(i); if (t1 == null) { if (!A.GetValueTyped(i).Equals(null)) return false; } else { if (!t1.Equals(A.GetValueTyped(i))) return false; } } } return true; } /// /// generate a hash code based on the current arrays values /// /// hash code /// The hashcode is generated by taking the values currently stored in the array into account. /// Therefore, the function must iterate over all elements in the array - which makes it somehow a expensive /// operation. Take this into account, if you consider using large arrays in collections like dictionaries /// or hashtables, which make great use of hash codes. public override int GetHashCode() { if (IsDisposed) return base.GetHashCode(); int ret = Size.GetHashCode(); ElementType[] data = GetArrayForRead(); ret = (ret * 17) + data.Length; foreach (ElementType t in data) { ret = unchecked( ret * 17 ); if (t != null) ret = unchecked(ret + t.GetHashCode()); } return (int)ret; } #endregion #region subarray + range get / set /// /// Alter values specified by range. /// /// ILRange specifying the dimensions/indices to be altered. /// new values /// /// The values pointed to by range will be replaced with the values /// found in 'values'. Important: the range cannot specify indices outside of my dimensions! /// Therefore, the storage must have been expanded in advance, if needed! public virtual 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; ElementType[] 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 ElementType scalar = values.GetValueTyped(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; ) { // we need a upward counter variable anyway, initialized with // higherDimSum. So we simply take that and reset it after the loop: myArr[ higherDimSum++ ] = scalar; } higherDimSum += (rng[0][i]-1); // negative value in rng! } else { myArr[ higherDimSum + rng[0][i] ] = scalar; } } // 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][0] < 0) { inFullDim[d] = rng[d][idxArr[d]]; } else { higherDimSum += (rng[d][0] * seqDistances[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 } else { #region non scalar case ElementType [] 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; ) { myArr[ higherDimSum++ ] = valuesArr[ valuesPos++ ]; } higherDimSum += (rng[0][i]-1); // negative value in rng! } else { myArr[ higherDimSum + rng[0][i] ] = valuesArr[ 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]]; } else { higherDimSum += (rng[d][0] * seqDistances[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 } } internal virtual 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"); ElementType[] myArr = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { ElementType scal = values.GetValueTyped(0); for (int i = 0; i < myArr.Length; i++) { myArr[i] = scal; } } else { ElementType[] valArr = values.GetArrayForRead(); System.Array.Copy(valArr,myArr,Size.NumberOfElements); } } /// /// 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 virtual 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."); using (ILScope.Enter(indices)) { #region set full shortcut if (indices is ILFullRange || object.Equals(indices, null)) { int pos; ElementType[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ElementType val = values.GetValueTyped(0); while (pos-- > 0) 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 (ElementType val in values) { 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"); } ElementType[] myArray = GetArrayForWrite(); double[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; if (values.Size.NumberOfElements == 1) { ElementType scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; ) { myArray[(int)indArray[i++]] = scalarElement; } } else { ElementType[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { 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 virtual 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."); using (ILScope.Enter(indices)) { #region set full shortcut if (indices is ILFullRange || object.Equals(indices, null)) { int pos; ElementType[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ElementType val = values.GetValueTyped(0); while (pos-- > 0) 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 (ElementType val in values) { 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"); } ElementType[] myArray = GetArrayForWrite(); Int64[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; if (values.Size.NumberOfElements == 1) { ElementType scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; ) { myArray[(int)indArray[i++]] = scalarElement; } } else { ElementType[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { 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 virtual 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."); using (ILScope.Enter(indices)) { #region set full shortcut if (indices is ILFullRange || object.Equals(indices, null)) { int pos; ElementType[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ElementType val = values.GetValueTyped(0); while (pos-- > 0) 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 (ElementType val in values) { 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"); } ElementType[] myArray = GetArrayForWrite(); Int32[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; if (values.Size.NumberOfElements == 1) { ElementType scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; ) { myArray[(int)indArray[i++]] = scalarElement; } } else { ElementType[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { 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 virtual 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."); using (ILScope.Enter(indices)) { #region set full shortcut if (indices is ILFullRange || object.Equals(indices, null)) { int pos; ElementType[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ElementType val = values.GetValueTyped(0); while (pos-- > 0) 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 (ElementType val in values) { 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"); } ElementType[] myArray = GetArrayForWrite(); Int16[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; if (values.Size.NumberOfElements == 1) { ElementType scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; ) { myArray[(int)indArray[i++]] = scalarElement; } } else { ElementType[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { 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 virtual 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."); using (ILScope.Enter(indices)) { #region set full shortcut if (indices is ILFullRange || object.Equals(indices, null)) { int pos; ElementType[] myArray = GetArrayForWrite(); if (values.Size.NumberOfElements == 1) { pos = Size.NumberOfElements; ElementType val = values.GetValueTyped(0); while (pos-- > 0) 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 (ElementType val in values) { 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"); } ElementType[] myArray = GetArrayForWrite(); float[] indArray = indStorage.GetArrayForRead(); int len = indices.Size.NumberOfElements; if (values.Size.NumberOfElements == 1) { ElementType scalarElement = values.GetValueTyped(0); for (int i = 0; i < len; ) { myArray[(int)indArray[i++]] = scalarElement; } } else { ElementType[] valArray = values.GetArrayForRead(); for (int i = 0; i < len; ) { myArray[(int)indArray[i]] = valArray[i++]; } } } else { throw new ILArgumentException("storage type of given indices is not supported"); } } } #endregion HYCALPER AUTO GENERATED CODE /// /// Create referencing or solid array from this array, with shifted dimensions. /// /// Number of dimensions to shift the array. /// Shifted ILDenseStorage of the same type. /// Shift is done 'to the left'. public virtual ILDenseStorage ShiftDimensions (int shift) { return CreateShiftedStorage(shift); } #endregion #region Reshape, Concat, Repmat - overriding ILBaseArray /// /// reshape this storage /// /// new dimensions of the storage. /// This storage will be changed! The operation is cheap, since the /// number of elements (and their values) do not change. The same countable array /// is used in conjunction with a new dimension specifier. /// /// If the number of elements in 'newDimension' /// do not match the number of elements in this storage. internal void Reshape(ILSize newDimensions) { if (newDimensions.NumberOfElements != m_size.NumberOfElements) throw new ILArgumentSizeException ("the number of elements must not change"); m_size = newDimensions; } /// /// reshape this storage /// /// new dimension length of the storage. /// This storage will be changed! The operation is cheap, since the /// number of elements (and their values) do not change. The same underlying storage /// is used in conjunction with the new dimension specifier. /// /// If the number of elements in 'newDimension' /// do not match the number of elements in this storage. public void Reshape(params int[] dims) { ILSize newDimension = new ILSize(dims); Reshape(newDimension); } /// /// concatenate this storage /// /// n dimensional storage /// Index of dimension along which to concatenate the arrays. /// If dim is larger than the number of dimensions of one of the arrays /// its value will be used in modulus. /// Array having the size of both input arrays laid beside one /// another along the 's-dimension /// The array returned will be a copy of both arrays involved. None /// of the input arrays will be altered. public virtual ILDenseStorage Concat(ILDenseStorage A, int dim) { ILSize inDim = A.m_size; for (int i = 0; i < Math.Max(inDim.NumberOfDimensions, m_size.NumberOfDimensions); i++) { if (i != dim) if (m_size[i] != inDim[i]) throw new ILArgumentSizeException("the length of dimensions of both arrays (except the dimension " + "to be concatenated) must match"); } // concatenate if (inDim.NumberOfElements == 1 && m_size.NumberOfElements == 1) { // both scalars int[] dims = new int[2] { 1, 1 }; dims[dim] = 2; ElementType[] retArr = ILMemoryPool.Pool.New(2); retArr[0] = m_data.Data[0]; retArr[1] = A.m_data.Data[0]; return CreateSelf(retArr, new ILSize(dims)); } int lenOutArr = m_size.NumberOfElements + inDim.NumberOfElements; int[] retDims = m_size.ToIntArray(dim+1); retDims[dim] += inDim[dim]; ILSize retDimension = new ILSize(retDims); ElementType[] retData = ILMemoryPool.Pool.New(retDimension.NumberOfElements); ElementType[] myData = GetArrayForRead(); ElementType[] inData = A.GetArrayForRead(); int len1 = m_size.SequentialIndexDistance(dim + 1); int len2 = inDim.SequentialIndexDistance(dim + 1); int posOutArr = 0, inPos = 0, myPos = 0; while (posOutArr < lenOutArr) { for (int i = 0; i < len1; i++) retData[posOutArr++] = myData[myPos++]; for (int i = 0; i < len2; i++) retData[posOutArr++] = inData[inPos++]; } return CreateSelf(retData,retDimension); } /// /// Replicate this storage to create a larger array. /// /// Sizes description. This may be a /// list or an array of integer values. If the number of elements in is /// less the number of dimensions in this array, the trailing dimensions will /// be set to 1 (singleton dimensions). On the other hand, if the number specified /// is larger then the number of dimensions of this array, the result /// will have its number of dimensions extended accordingly. /// array which is made out of multiple copies of this array along /// specified dimensions, according to . internal virtual ILDenseStorage Repmat(params int[] sizes) { if (m_size.NumberOfElements == 0) return CreateSelf(new ILSize(sizes)); ILRightSideRange rsRange = new ILRightSideRange(m_size, sizes); return CreateSubarrayStorage(rsRange); // experimental: via subindexing full dimensions //ILBaseArray[] dimArrays = new ILBaseArray[dims.Length]; //for (int i = 0; i < dimArrays.Length; i++) { // dimArrays[i] = ILMath.cell(ILMath.full)[ILMath.zeros(1,dims[i])]; //} //return Subarray(dimArrays); //build return dimensions //int[] newDim = new int[Math.Max(dims.Length, m_dimensions.NumberOfDimensions)]; //for (int d = 0; d < newDim.Length; d++) { // if (d < dims.Length) { // newDim[d] = m_dimensions[d] * dims[d]; // } else { // newDim[d] = m_dimensions[d]; // } //} //ILSize outDim = new ILSize(true, newDim); //if (m_dimensions.NumberOfElements == 0 || outDim.NumberOfElements == 0) // return new ILDenseStorage(new ILCountableArray(0), outDim); //ILDenseStorage ret = new ILDenseStorage( // new ILCountableArray(outDim.NumberOfElements), outDim); //ElementType[] retArray = ret.GetArrayForWrite(); //ElementType[] myArray = GetArrayForRead(); //int[] outStrides = outDim.GetSequentialIndexDistances(m_dimensions.NumberOfDimensions); //int[] myStrides = m_dimensions.GetSequentialIndexDistances(m_dimensions.NumberOfDimensions); //retArray[0] = myArray[0]; //if (outDim.NumberOfElements < ILNumerics.Settings.s_minParallelElement1Count) { // for (int outPos = 1; outPos < outDim.NumberOfElements; ) { // int inPos = 0; // for (int d = m_dimensions.NumberOfDimensions; d-- > 0; ) { // inPos += ((outPos / outStrides[d]) % m_dimensions[d]) // * myStrides[d]; // } // retArray[outPos++] = myArray[inPos]; // } //} else { // System.Threading.Tasks.Parallel.For(1,outDim.NumberOfElements, i => { // int inPos = 0; // for (int d = m_dimensions.NumberOfDimensions; d-- > 0; ) { // inPos += ((i / outStrides[d]) % m_dimensions[d]) // * myStrides[d]; // } // retArray[i] = myArray[inPos]; // }); //} //return ret; } /// /// Remove individual parts of a dimension from this storage /// /// index of the dimension, where indices are to be removed /// indices to be removed from , -1 for "wipe" (make this an empty storage) /// The function directly operates on this storage! After the function returns, /// this storage may have its dimensions changed! internal virtual void Remove(int dimension, ILIntList indices) { using (ILScope.Enter()) { if (dimension >= Size.NumberOfDimensions) throw new ILArgumentException("index out of range"); if (dimension == -1) { Data = new ILCountableArray(0); m_size = ILSize.Empty00; return; } // TODO: may should be replaced with a faster (&fancier? ) version... ?? ILBaseArray[] dims = new ILBaseArray[Size.NumberOfDimensions]; ILIntList keepInd = ILIntList.Create(); ILIntList remvInd = indices; int max = Size[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 int keepIndCount = keepInd.Count; ILArray remIndices = ILMath.array(keepInd.GetArray(), new ILSize(1, keepIndCount)); if (remIndices.Size.NumberOfElements == Size[dimension]) { // nothing to do return; } for (int i = 0; i < dims.Length; i++) { dims[i] = ILMath.full; } dims[dimension] = remIndices; ILDenseStorage ret = Subarray(dims); Dispose(); // this will for reference element types (e.g. ILCell) also dispose the removed elements Data = ret.Data; m_size = ret.Size; } } #endregion #region serialize /// /// Prepare for serialization. /// /// Streaming Context - provided by the formatter. /// nothing to do here [OnSerializing] private void OnSerialize(StreamingContext context) { } /// /// Post operations aftre deserializing is finished. /// /// Streaming context provided by the formatter. /// nothing to do here [OnDeserialized] void OnDeserialized(StreamingContext context) { } #endregion #region single element access /// /// Get single value from this storage. /// /// Integer array holding the dimension specifier /// Element at the position pointed to by idx. internal override object GetValue(params int[] idx) { return GetValueTyped(idx); } /// /// Get single value from this storage. /// /// Integer array holding the dimension specifier /// Element at the position pointed to by idx. internal override ElementType GetValueTyped(params int[] idx) { if (idx.Length == 1) return m_data.Data[idx[0]]; int destIdx = idx[0], d, highDims; if (destIdx >= m_size[0] || destIdx < 0) throw new ILArgumentException("GetValue: index out of bound for dimensions: 0"); int [] seqDist = m_size.GetSequentialIndexDistances(0); if (idx.Length <= m_size.NumberOfDimensions) { for (d = 1; d < idx.Length - 1; d++) { if (idx[d] >= m_size[d] || idx[d] < 0) throw new ILArgumentException("GetValue: index out of bound for dimensions: " + d.ToString()); destIdx += idx[d] * seqDist[d]; } for (highDims = idx[d]; d 0; d++) { destIdx += (highDims % m_size[d]) * seqDist[d]; highDims /= m_size[d]; } if (highDims > 0) throw new ILArgumentException ("GetValue: index out of bound!"); return m_data.Data[destIdx]; } else { highDims = m_size.NumberOfDimensions; for (d = 1; d < highDims; d++) { if (idx[d] >= m_size[d] || idx[d] < 0) throw new ILArgumentException("GetValue: index out of bound for dimensions: " + d.ToString()); destIdx += idx[d] * seqDist[d]; } for (; d(new ElementType[1] { GetValueTyped(innerIndices) }, ILSize.Scalar1_1); } internal override ILBaseArray GetAsBaseArray() { return new ILRetArray((ILDenseStorage)Clone()); } /// /// Get single value from this storage by a single sequential access. /// /// Integer array holding the dimension specifier /// pointing to the value. /// Out value: return position mapped to dimensions. /// Object in the position pointed to by idx. /// dims is the final position into the array for the sequential index specification idx. internal override object GetValueSeq(int idx, ref int[] dims) { int IdxCpy = idx; for (int d = 0; d /// Set single value to element at the specified index. /// /// New value. /// Index of the element to be altered. internal override void SetValue(object value, params int[] idx) { try { SetValueTyped((ElementType)value, idx); } catch (InvalidCastException) { SetValueTyped((ElementType)Convert.ChangeType(value, typeof(ElementType)), idx); } } /// /// Set value of element at the specified position. /// /// new value /// position of the element to be altered /// This function does support automatic expansion of the array /// if indices lay outside the dimension limits of the array. However, because /// of ambiguity reasons this is not reliable supported for vector sized arrays. internal override void SetValueTyped(ElementType value, params int[] idx) { try { if (idx.Length < 2) { if (idx.Length == 1) { if (idx[0] >= m_size.NumberOfElements) throw new IndexOutOfRangeException(); GetArrayForWrite()[idx[0]] = value; } return; } int i = m_size.IndexFromArray(idx); if (i >= m_size.NumberOfElements) throw new IndexOutOfRangeException(); GetArrayForWrite()[i] = (ElementType)value; } catch (Exception exc) { if (exc is ILArgumentException || exc is IndexOutOfRangeException ) { // expanding ? int [] dimensions = m_size.ToIntArray(Math.Max(idx.Length,m_size.NumberOfDimensions)); bool mustExpand = false; int i = m_size.IndexFromArray(ref mustExpand, ref dimensions, idx); if (mustExpand) { ExpandArray(dimensions); m_data.Data[i] = value; } else { throw; } } } } /// /// [depricated] Convert index array into sequential index for storage access. /// /// int array with dimension specification. /// Index of requested value inside the solid storage. This /// value can directly be used to query the corresponding value via GetArrayForRead()[return_value]. /// /// This function is deprecated! Use instead!
/// If the length of idx is smaler than the number of dimensions /// of this storage, the trailing dimensions will be replaced with "0". I.e /// the first index of each non specified dimension will be used. /// If length of idx is larger than the dimensions of this storage, the behavior /// is undefined. Therefore this function should be enclosed in try, catch blocks /// to handle this case!
internal int getBaseIndex(params int[] idx) { // arghs! -> ugly! piuh!! if (idx == null) throw new ILArgumentException("indices specified must not be null"); if (idx.Length < m_size.NumberOfDimensions) { bool dummy; int [] tmp = ILMemoryPool.Pool.New(m_size.NumberOfDimensions,true, out dummy); for (int i = 0; i < idx.Length; i++) { tmp[i] = idx[i]; } return m_size.IndexFromArray(tmp); } return m_size.IndexFromArray(idx); } /// /// [depricated] Convert index array into sequential index for storage access. Ommit any bound checking. /// /// int array with dimensions specification. /// Output parameter. On return determine, if the index /// specification points outside of the dimensions of this ILDenseStorage and the array /// must be expanded before accessing elements on that position. /// if the array was found to be expanded, this are the /// needed dimension sizes for the new array. The sizes are computed from the range /// specification given. /// Index of requested value inside the solid storage. This /// value may directly be used to query the value via m_data[return_value]. /// The value returned is valid for solid storages as well as for reference /// storages. /// /// /// idx must be not null and must contain at least one element. /// If the length of idx is smaler than the number of dimensions /// of this storage, the trailing dimensions will be replaced with "0". I.e /// the first index of each non specified dimensions will be used. /// If length of idx is larger than the dimensions of this storage, the index of /// the expanded array will be returned. internal int getBaseIndex(ref bool MustExpand, ref int[] dimensions, params int[] idx) { int destIdx = 0; if (idx.Length == 1) { destIdx = idx[0]; if (destIdx < 0) throw new ILArgumentException("check index for dimension 0!"); if (destIdx >= m_size.NumberOfElements) { MustExpand = true; dimensions[0] = destIdx + 1; } return destIdx; } return m_size.IndexFromArray(ref MustExpand, ref dimensions, idx); } /// /// Copy values of all elements into System.Array. /// /// System.Array, holding all element values of this ILDenseStorage. /// The System.Array may be predefined. If its length is sufficient, it will be used and /// its leading elements will be overwritten when function returns. If 'result' is null or has too few elements, /// it will be recreated from the ILNumerics memory pool. public void ExportValues(ref ElementType[] result) { if (result == null || result.Length < m_size.NumberOfElements) result = ILMemoryPool.Pool.New(m_size.NumberOfElements); int pos = 0; foreach (ElementType v in this) { result[pos++] = v; } } /// /// Get direct reference to inner System.Array storage for write access /// /// reference to inner System.Array /// Altering this array can be done directly. If necessary, the array is detached before /// returned. Watch the column order format of storages in ILNumerics! Keep in minds, the length /// of the array may exceeds the number of elements. /// Accessing the inner system array directly should be left to ILNumerics experts only! /// Unless you really know, what you are doing, you should rather use the higher order access /// methods provided by ILArray<T>! (You have been warned!) internal ElementType[] GetArrayForWrite() { if (m_data.ReferenceCount > 1) { Detach(); } return m_data.Data; } /// /// Get direct reference to inner System.Array storage for read access /// /// reference to inner System.Array for reading /// This method is provided for experts only! Altering elements of this /// array may cause the data to be invalidated or corrupted! Use this array only for reading! Note /// the ILNumerics array storage format (column major). Keep in mind, the length /// of the array may exceeds the number of elements! /// Accessing the inner system array directly should be left to ILNumerics experts only! /// Unless you really know, what you are doing, you should rather use the higher order access /// methods provided by ILArray<T>! (You have been warned!) internal ElementType[] GetArrayForRead() { //if (PendingTasks > 0) // System.Threading.SpinWait.SpinUntil(() => { return PendingTasks == 0; }); return m_data.Data; } #endregion /// /// Create lazy,shallow copy of this array /// /// ILDenseStorage as copy of this storage. /// The ILDenseStorage object returned will be of the same size and type than this object. /// The copy is done lazy. This means, the new storage will at first share the memory /// with that storage. This will take almost no memory / processor time. As soon as attempts /// are made to alter the new storage, it will be detached from this storage and use own memeory. internal override ILStorage Clone() { return CreateSelf(m_data,m_size); } internal ILCountableArray GetDataArray() { return m_data; } internal virtual void IndexSubrange(ILDenseStorage value, ILBaseArray[] range) { using (ILScope.Enter(range)) { if (Object.ReferenceEquals(value, null) || value.Size.NumberOfElements == 0) { #region remove if (range == null) return; ILLeftSideRange rng = new ILLeftSideRange(Size, range); if (rng.Expanding) { throw new ILArgumentException("invalid range for removal specified"); } if (rng.Size.NumberOfElements == 0) { return; } int nonFullDims = 0; int dimIdx = -1; // check validity for (int i = 0; i < rng.RangeArray.Length; i++) { if (rng[i].Count != 1 || rng[i][0] >= 0) { if (++nonFullDims > 1) throw new ILArgumentException("for removal only one dimension can be 'non-full'"); dimIdx = i; foreach (int ind in rng[i]) { if (ind < 0) { throw new ILArgumentException("invalid removal indices: all but at most one dimensions must be specified as 'full'. check dimension #" + i.ToString()); } } } } // remove ILSize newDim = new ILSize(Size.ToIntArrayEx(rng.RangeArray.Length)); ILSize oldDimensions = Size; try { Reshape(newDim); // <- cheap! if (dimIdx >= 0) { Remove(dimIdx, rng[dimIdx]); // <- expensive! } else { // all dims full specified Remove(dimIdx, null); // <- expensive! } } catch (Exception) { Reshape(oldDimensions); throw; } #endregion } else { #region setrange if (range == null || range.Length == 0) { return; } else if (range.Length == 1) { if (range[0] is ILDenseArray) { SetRange(range[0] as ILDenseArray, value); return; } else if (range[0] is ILDenseArray) { // special case? A[":;0:3;0:end;..."] -> multiple dimensions given as single string string indStr = (string)(range[0] as ILDenseArray).GetValue(0); string[] dimParts = indStr.Split(';'); if (dimParts.Length == 0) { // empty range given return; } else if (dimParts.Length > 1) { range = new ILBaseArray[dimParts.Length]; for (int i = 0; i < dimParts.Length; i++) { range[i] = dimParts[i]; } // re-enter function to push the new arrays into scope IndexSubrange(value,range); return; } else { ILBaseArray indices = ILRange.ParseDimension(indStr, Size.NumberOfElements); if (indices is ILBaseArray) { SetRangeFull(value); } else { SetRange(indices as ILDenseArray, value); } return; } } else if (range[0] is ILDenseArray) { SetRange(range[0] as ILDenseArray, value); return; } else if (range[0] is ILDenseArray) { SetRange(range[0] as ILDenseArray, value); return; } else if (range[0] is ILDenseArray) { SetRange(range[0] as ILDenseArray, value); return; } else if (range[0] is ILLogical) { SetRange(ILNumerics.ILMath.find(range[0] as ILLogical), value); return; } else if (range[0] is ILRetLogical) { SetRange(ILNumerics.ILMath.find(range[0] as ILRetLogical), value); return; } } ILLeftSideRange rng = new ILLeftSideRange(Size, range); if (rng.Expanding) { ExpandArray(rng); } SetRange(rng, value); #endregion } } } #region IEnumerable> Member /// /// enumerator returning elements as ElementType /// public override IEnumerator GetEnumerator ( ) { int len = m_size.NumberOfElements; ElementType[] myData = GetArrayForRead(); for (int i = 0; i < len; i++) yield return myData[i]; } #endregion #region private helper /// /// helper function to gather some parameters for partial dimension removal /// /// object with index specifications. May be of /// type ILBaseArray[] with numeric arrays or a string array according /// to the format of . /// /// Out parameter: index of dimension the indices to be removed lie in. /// Indices to be removed. /// Dimension structure, can be used to reshape the storage before the removal /// If range comprises a range dimension specification which is smaller than /// the actual number of dimension of this storage, the storage must be reshaped in advance of the removal. /// This reshaping proccess will not be done inside this function! However /// the dimension value returned reflects the size of the storage before removing and therefore /// can be utilized for reshaping the storage. /// If: /// The length of range exceeds the dimensions of this storage. /// More than one or less than one dimension of range was not null. /// The type of range was invalid, or /// Range is of type , but the element type is not numeric /// internal void ExtractRemovalParameter(ILBaseArray[] rng, out int dimensionIdx, ref ILIntList indices, out ILSize dimensions) { dimensionIdx = 0; dimensions = null; if (rng.Length > m_size.NumberOfDimensions) throw new ILArgumentException("Error removing: dimension specification exceeds matrix dimensions."); int specCount = 0; int tmp = 0; if (rng.Length == 1 && rng[0] is ILBaseArray) { string allRangeString = (string)(rng[0] as ILBaseArray).GetValue(0); string[] ranges = allRangeString.Split(';'); if (ranges.Length > 1) { rng = new ILBaseArray[ranges.Length]; for (int i = 0; i < ranges.Length; i++) { rng[i] = ranges[i]; } } } int[] outDim = Size.GetReshapedSize(rng.Length); for (int i = 0; i < rng.Length; i++) { if (object.Equals(rng[i], null)) { // nothing to remove if (indices != null) { indices.Clear(); } return; } else if (!rng[i].IsEmpty) { if (rng[i] is ILDenseArray) { string stringVal = (rng[i] as ILDenseArray).GetValue(0); ILBaseArray indFromString = ILRange.ParseDimension(stringVal,outDim[i]); if (!(indFromString is ILBaseArray)) { if (specCount++ > 0) { throw new ILArgumentException("only one dimension can be non-fully specified for removal"); } dimensionIdx = i; indices = new ILIntList(indFromString as ILDenseArray); } continue; } dimensionIdx = i; if (specCount++ > 0) { throw new ILArgumentException("only one dimension can be non-fully specified for removal"); } if (rng[i] is ILBaseArray) { // A[end + ...] given Expression expr = (rng[i] as ILBaseArray).GetValue(0); int exprVal = ILExpression.Evaluate(expr, Size[i] - 1); indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add(exprVal); } } else if (rng[i] is ILLogical) { ILArray ind = ILNumerics.ILMath.find((ILLogical) rng[i]); tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } } else if (rng[i] is ILRetLogical) { ILArray ind = ILNumerics.ILMath.find((ILRetLogical) rng[i]); tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } /* !HC:TYPELIST: inArr1 float Int16 Int32 Int64 byte */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } #region HYCALPER AUTO GENERATED CODE /* !HC:TYPELIST: */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } /* !HC:TYPELIST: */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } /* !HC:TYPELIST: */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } /* !HC:TYPELIST: */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } /* !HC:TYPELIST: */ } else if (rng[i] is ILDenseArray ) { ILDenseArray ind = rng[i] as ILDenseArray ; tmp = ind.Size.NumberOfElements; indices = ILIntList.Create(); for (int p = 0; p < tmp; p++) { indices.Add((int)ind.GetValue(p)); } #endregion HYCALPER AUTO GENERATED CODE } else throw new ILArgumentTypeException("error removing: invalid dimensions specifier, dimension #" + i.ToString()); } } if (indices == null) { dimensionIdx = 0; dimensions = m_size; //indices = new int[0] { }; return; } // if only one dimension specified -> make row vector //if (rng.Length < 2) { // outDim[1] = outDim[0]; // outDim[0] = 1; // dimensionIdx = 1; //} dimensions = new ILSize(outDim); } /// /// Expanded this storage for index addressing outside of my dimensions /// /// range specification with size for destination array internal void ExpandArray (ILLeftSideRange range) { int[] outDims; int i= 0; ILSize outDimensions; if (range.Size.NumberOfDimensions > m_size.NumberOfDimensions) { outDims = new int[range.Size.NumberOfDimensions]; for (; i < m_size.NumberOfDimensions; i ++) { outDims[i] = (range.ExpandDimensions[i] > m_size[i]) ? range.ExpandDimensions[i] : m_size[i]; } for(; i < range.Size.NumberOfDimensions; i++) outDims[i] = range.ExpandDimensions[i]; } else { outDims = new int[m_size.NumberOfDimensions]; for (; i < range.Size.NumberOfDimensions; i ++) { outDims[i] = (range.ExpandDimensions[i] > m_size[i]) ? range.ExpandDimensions[i] : m_size[i]; } for(; i < m_size.NumberOfDimensions; i++) outDims[i] = m_size[i]; } outDimensions = new ILSize(outDims); ElementType [] outData = ILMemoryPool.Pool.New(outDimensions.NumberOfElements); // transfer old data to new array int [] tmpIdx = new int[outDims.Length]; for (i = 0; i < m_size.NumberOfElements; i++) { ElementType tmp = (ElementType)GetValueSeq(i,ref tmpIdx); outData[outDimensions.IndexFromArray(tmpIdx)] = tmp; } // exchange my data Data = new ILCountableArray(outData, outDimensions.NumberOfElements); m_size = outDimensions; } /// /// Expand this storage for index addressing outside of my dimensions /// /// sizes of dimensions for the new storage protected void ExpandArray(int[] indices) { if (indices.Length == 2 && (indices[0] * indices[1] == 0)) { if (indices[0] > 0) indices[1] = 1; else if (indices[1] > 0) indices[0] = 1; } ILSize outDimensions = new ILSize(indices); bool cleared; ElementType [] outData = ILMemoryPool.Pool.New(outDimensions.NumberOfElements,true,out cleared); // transfer old data to new array int [] tmpIdx = new int[indices.Length]; for (int i = 0; i < m_size.NumberOfElements; i++) { ElementType tmpData = (ElementType)GetValueSeq(i,ref tmpIdx); outData[outDimensions.IndexFromArray(tmpIdx)] = tmpData; } // replace with my data Data = new ILCountableArray(outData,outDimensions.NumberOfElements); m_size = outDimensions; } /// /// Copy upper triangular part of this array into new solid array. /// /// Length of first dimension of destination array. /// Solid array of size [n x {ThisColumnCount})]. internal ILDenseStorage copyUpperTriangle(int n) { ILDenseStorage ret = new ILDenseStorage(new ILSize(n,n)); ElementType[] arr = ret.GetArrayForWrite(); ElementType[] myData = GetArrayForRead(); if (m_size[0] == n) { for (int rcount = 0 , pos = 0; rcount < n; rcount++) { for (int i = 0; i <= rcount; i++) { arr[pos] = myData[pos++]; } pos += (n - rcount - 1); } } else { for (int rcount = 0 , posIn = 0, posOut = 0, lenA = m_size[0]; rcount < n; rcount++) { for (int i = 0; i <= rcount; i++) { arr[posOut++] = myData[posIn++]; } posOut += (n - rcount - 1); posIn += (lenA - rcount - 1); } } return ret; } /// /// Copy lower triangular part of this array into new solid array. /// /// Solid array of same size than this array. /// If this is not a 2D array, only the first dimension is referenced. internal ILDenseStorage copyLowerTriangle() { int n = m_size[0],pos = 0; ILDenseStorage ret = new ILDenseStorage(new ILSize(n,n)); ElementType[] arr = ret.GetArrayForRead(); ElementType[] myData = GetArrayForRead(); for (int c = 0; c < m_size[1]; c++) { pos += c; for (int r = c; r < n; r++,pos++) { arr[pos] = myData[pos]; pos++; } } return ret; } #endregion } }