Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILCell.cs @ 9310

Last change on this file since 9310 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 20.5 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Text;
42using ILNumerics.Storage;
43using ILNumerics.Exceptions;
44using System.Collections.Generic;
45
46namespace ILNumerics {
47    /// <summary>
48    /// ILCell: container class holding and managing arbitrary array objects
49    /// </summary>
50    /// <remarks>
51    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type.
52    /// Read and write access to cells provide value semantics - changes on arrays stored inside/ and
53    /// retrieved from a cell cannot change the corresponding original array.
54    /// </remarks>
55    [Serializable]
56    public sealed class ILCell : ILBaseCell {
57
58        private static readonly bool s_isTempArray = false;
59
60        #region constructors
61        /// <summary>
62        /// Create cell object with pre-created data in specified dimensions
63        /// </summary>
64        /// <param name="data">predefined element data array, will be used for new cell (no copy will be made)</param>
65        /// <param name="size">size of the new cell</param>
66        /// <remarks>object array data will directly be used for storage. No
67        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
68        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
69        internal ILCell(ILStorage[] data, params int[] size)
70            : base(new ILCellStorage(data, new ILSize(size)), s_isTempArray) {
71        }
72        /// <summary>
73        /// Create cell object with pre-created data in specified dimensions
74        /// </summary>
75        /// <param name="data">predefined element data array, will be used for new cell (no copy will be made)</param>
76        /// <param name="size">size of the new cell</param>
77        /// <remarks>object array data will directly be used for storage. No
78        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
79        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
80        internal ILCell(ILStorage[] data, ILSize size)
81            : base(new ILCellStorage(data, size), s_isTempArray) {
82        }
83        /// <summary>
84        /// [deprecated] create new cell object, elements will be 'null'
85        /// </summary>
86        /// <param name="size">dimension sizes of the new cell</param>
87        /// <remarks><para>After creation, the cell elements can be set by use
88        /// of the indexer methods or by using corresponding methods of ILCell like SetValue()</para>
89        /// <para>Consider using <see cref="M:ILNumerics.ILMath.cell()"/> in order to create
90        /// cell arrays.</para></remarks>
91        /// <seealso cref="P:ILNumerics.ILCell.Item(System.Int32[])"/>
92        /// <seealso cref="P:ILNumerics.ILCell.Item(ILNumerics.ILBaseArray[])"/>
93        /// <seealso cref="ILNumerics.ILBaseCell.GetArray{_T}(ILNumerics.ILBaseArray[])"/>
94        [Obsolete("use <see cref='ILNumerics.ILMath.cell(ILSize)'/> instead!")]
95        public ILCell(params int[] size)
96            : base(new ILCellStorage(new ILStorage[prod(size)], new ILSize(size)), s_isTempArray) {  }
97
98        internal ILCell(ILCellStorage cellStorage)
99            : base(cellStorage, s_isTempArray) { }
100
101        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
102        internal ILCell(ILSize size, params ILStorage[] values)
103            : base(new ILCellStorage(values, size), s_isTempArray) { }
104
105        #endregion constructors
106
107        #region properties
108        /// <summary>
109        /// Replace the elements of this array with another array's elements, preventing memory leaks
110        /// </summary>
111        /// <param name="value">New array</param>
112        public ILRetCell a {
113            set { Assign(value); }
114            get { return this.C; }
115        }
116        #endregion
117
118        #region implicit casts
119       
120        #region constructional operators
121        //public static implicit operator ILCell(double value) {
122        //    return createScalar(value);
123        //}
124        //public static implicit operator ILCell(float value) {
125        //    return createScalar(value);
126        //}
127        //public static implicit operator ILCell(byte value) {
128        //    return createScalar(value);
129        //}
130        //public static implicit operator ILCell(int[] value) {
131        //    return createArray(value);
132        //}
133        #endregion
134
135        #region conversional operators
136        /// <summary>
137        /// Convert temporary cell to persistent cell
138        /// </summary>
139        /// <param name="A">Temporary cell</param>
140        /// <returns>Persistent cell</returns>
141        public static implicit operator ILCell(ILRetCell A) {
142            if (object.Equals(A, null))
143                return null;
144            ILCell ret = new ILCell((ILCellStorage)A.GiveStorageAwayOrClone());
145            ILScope.Context.RegisterArray(ret);
146            return ret;
147        }
148        /// <summary>
149        /// Convert input parameter cell to persistent cell
150        /// </summary>
151        /// <param name="A">Input parameter cell</param>
152        /// <returns>Persistent cell</returns>
153        public static implicit operator ILCell(ILInCell A) {
154            if (object.Equals(A, null))
155                return null;
156            ILCell ret = new ILCell(new ILCellStorage(
157                A.Storage.GetDataArray(), A.Size));
158            ILScope.Context.RegisterArray(ret);
159            return ret;
160        }
161        /// <summary>
162        /// Convert output parameter cell to persistent cell
163        /// </summary>
164        /// <param name="A">Output parameter cell</param>
165        /// <returns>Persistent cell</returns>
166        public static implicit operator ILCell(ILOutCell A) {
167            if (object.Equals(A, null))
168                return null;
169            ILCell ret = new ILCell(new ILCellStorage(
170                A.Storage.GetDataArray(), A.Size));
171            ILScope.Context.RegisterArray(ret);
172            return ret;
173        }
174        #endregion
175
176        #endregion
177
178        #region helper functions
179        internal static long prod(int[] sizes) {
180            int ret = 1;
181            for (int i = 0; i < sizes.Length; i++)
182                ret *= sizes[i];
183            return ret;
184        }
185        #endregion helper functions
186
187        #region public interface
188        /// <summary>
189        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
190        /// </summary>
191        /// <param name="value">New array</param>
192        public void Assign(ILRetCell value) {
193            if (!IsDisposed)
194                Storage.Dispose();
195            m_storage = value.GiveStorageAwayOrClone();
196            //ILScope.Context.RegisterArray(this); 
197        }
198        /// <summary>
199        /// Set single element of the cell
200        /// </summary>
201        /// <param name="value">The new value</param>
202        /// <param name="idx">Indices specifying the location to set the element to</param>
203        /// <remarks>The function supports the following features:
204        /// <list type="bullet">
205        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
206        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
207        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
208        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
209        /// </list>
210        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding
211        /// element is overwritten or removed.</para>
212        /// </remarks>
213        public void SetValue(ILBaseArray value, params int[] idx) {
214            using (ILScope.Enter(value)) {
215                Storage.SetValueTyped(value.Storage, idx);
216            }
217        }
218        /// <summary>
219        /// Set single element of the cell
220        /// </summary>
221        /// <param name="value">The new value</param>
222        /// <param name="idx">Indices specifying the location to set the element to</param>
223        /// <remarks>The function supports the following features:
224        /// <list type="bullet">
225        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
226        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
227        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
228        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
229        /// </list>
230        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding
231        /// element is overwritten or removed.</para>
232        /// </remarks>
233        internal void SetValue(ILStorage value, params int[] idx) {
234            Storage.SetValueTyped(value, idx);
235        }
236        /// <summary>
237        /// Alter range of this array
238        /// </summary>
239        /// <param name="value">Array with new values</param>
240        /// <param name="range">Range specification</param>
241        /// <remarks>All common array modification/ reshaping/ removing/ expansion rules apply.
242        /// <para>Like for almost all operations on cell, the values stored in the cell are
243        /// not connected to the original cell elements outside the cell (value semantics).</para></remarks>
244        public void SetRange(ILInCell value, params ILBaseArray[] range) {
245            using (ILScope.Enter(range))
246            using (ILScope.Enter(value)) {
247                if (Object.ReferenceEquals(value, null)) {
248                    Storage.IndexSubrange(null, range);
249                } else {
250                    Storage.IndexSubrange((ILCellStorage)value.Storage.Clone(), range);
251                }
252            }
253        }
254        #endregion
255
256        #region Index access
257        /// <summary>
258        /// Get/set/remove single element
259        /// </summary>
260        /// <paramref name="indices" value="Index to element"/>
261        /// <value>Inner element, new inner element or null</value>
262        /// <remarks>The type of access depends on the length of indices. If indices contains only one element,
263        /// the array will be accessed via sequential index access. This is sometimes called referred to as 'linear'
264        /// index addressing.
265        /// Sequential index access reflects the index of internal storage the way the data are actually organized
266        /// in memory. This access method is mainly convinient for vectors where you are not interested of orientation.
267        /// The following example demonstrates sequential index access for ILArray's (which also holds for ILCells):
268        /// <example>For <c>
269        /// ILArray&lt;double&gt; A = ILMath.counter(1,12);</c>, <c>A[2]</c> gives: 3.0.
270        /// But the transpose
271        /// <c>A.T[2]</c> gives also: 3.0.
272        /// For matrices and N-dimensional arrays this holds as well:
273        /// <code>
274        /// ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,3,2,2);
275        /// A =
276        /// [1.0 4.0
277        ///  2.0 5.0
278        ///  3.0 6.0
279        ///
280        ///  7.0 10.0
281        ///  8.0 11.0
282        ///  9.0 12.0]
283        ///
284        /// A = ILMath.Reshape(A,3,2,2);
285        /// A[10] gives 11.0
286        /// A[10,1] gives ILArgumentException -> out of range
287        /// A[2,1,1] gives 12.0
288        /// A[2,1] gives 6.0 (set trailing dimension to '0')</code></example>
289        /// <para>If the element addressed is a ILCell itself, a deep reference to this element will be returned instead.
290        /// I.e. all elements of the ILCell will be recursively replaced with references to itself. Therefore, altering the
291        /// elements returned will not alter the elements contained in the cell.</para>
292        /// <para>
293        /// <list type="bullet">
294        /// <listheader>The type of the element returned depends on the type of the element addressed:</listheader>
295        /// <item>For ILArray&lt;ElementType&gt; the array returned will be a clone of the original array.</item>
296        /// <item>For ILCell the ILBaseArray returned is a deep reference of the original elements stored.</item>
297        /// <item>For other types the behavior is undefined. (since other types are not implemented yet ;)</item>
298        /// </list> </para>
299        /// <para>This indexer may also be used for direct access to inner elements of (elements of elements of ...) this cell:
300        /// <example>
301        /// <code>
302        /// ILCell innerCell = new ILCell(2,1);
303        /// innerCell[0] = ILMath.vec(10,200);
304        /// innerCell[1] = new int[] {-10,-20,-30};
305        /// ILCell cell = new ILCell(2,1);
306        /// cell[0] = innerCell;
307        /// cell[1] = new string[] {"foobla"};
308        /// // cell is now:
309        /// // [ILCell,(1x2)]
310        /// //      [innerCell[0], ILArray&lt;double&gt;(1x181)]
311        /// //      [innerCell[0], ILArray&lt;double&gt;(1x3)]
312        /// // [ILArray&lt;string&gt;,(1x1)]
313        ///
314        /// cell[0,0] -&gt; will give innerCell eq. ILCell (1x2)
315        /// cell[0,1] -&gt; will give ILArray&lt;string&gt;
316        /// cell[0,0,0,1] -&gt; will give innerCell[1] eq. ILArray&lt;int&gt;(1x3)
317        /// </code>
318        /// </example>
319        /// In the last example above the trailing indices specified make the indexer walk down into the ILCell element and retrieve
320        /// the content of this element. This kind of index access may be done as deep as you want. Just
321        /// append the inner indices into inner elements to the right side of index specification. Addressing inner elements
322        /// this way is the only way to alter elements <b>directly</b> inside the ILCell. </para></remarks>
323        public ILRetCell this[params int[] indices] {
324            get {
325                ILStorage val = Storage.GetValueTyped(indices);
326                if (val is ILCellStorage)
327                    return new ILRetCell((ILCellStorage)val);
328                else
329                    return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
330            }
331            set {
332                using (ILScope.Enter(value)) {
333                    if (!object.Equals(value,null) && value.Storage.FromImplicitCast && value.IsScalar) {
334                        SetValue((value as ILDenseArray<ILStorage>).GetValue(0), indices);
335                    } else {
336                        SetValue((object.Equals(value,null)) ? null : value.Storage, indices);
337                    }
338                }
339            }
340        }
341
342        /// <summary>
343        /// Subarray access. Get/set regular subarray.
344        /// </summary>
345        /// <param name="indices">Address range</param>
346        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
347        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you
348        /// may ommit those trailing dimensions in <c>indices</c>.
349        /// <para>The indexer may be used for querying or altering single/any elements
350        /// in this cell. <c>indices</c> may contains index specifications for one to any
351        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
352        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by
353        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the
354        /// values returned will not alter the original elements.</para>
355        /// <para>The indexer may also be used for removing parts of the cell. Therefore null must be assigned to the range specified by <c>indices</c> (using the set-access). <c>indices</c>
356        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any
357        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be
358        /// merged and the array will be reshaped before applying the removal to it.
359        /// <example>
360        /// <code>
361        /// ILCell C = new ILCell(4,10);
362        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
363        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
364        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full!
365        /// </code></example></para>
366        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
367        /// </remarks>
368        public ILRetCell this[params ILBaseArray[] indices] {
369            get {
370                using (ILScope.Enter(indices)) {
371                    ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
372                    return new ILRetCell(elements);
373                }
374            }
375            set {
376                using (ILScope.Enter(indices))
377                using (ILScope.Enter(value)) {
378                    if (Object.ReferenceEquals(value, null)) {
379                        Storage.IndexSubrange(null, indices);
380                    } else {
381                        //if (value.Storage.FromImplicitCast && value.IsScalar) {
382                        //    Storage.IndexSubrange((ILDenseStorage<ILStorage>)value.GetValue(0), indices);
383                        //} else {
384                        Storage.IndexSubrange((ILCellStorage)value.Storage.Clone(), indices);
385                        //}
386                    }
387                }
388            }
389        }
390
391        #endregion index access
392
393        #region memory management
394        internal override bool EnterScope() {
395            return false;
396        }
397        #endregion
398    }
399}
Note: See TracBrowser for help on using the repository browser.