Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseCell.cs @ 11316

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

#1967: ILNumerics source for experimentation

File size: 21.1 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.Collections.Generic;
42using System.Linq;
43using System.Text;
44using ILNumerics.Storage;
45
46namespace ILNumerics {
47    /// <summary>
48    /// The class implements additional functionality needed for cells
49    /// </summary>
50    public class ILBaseCell : ILDenseArray<ILStorage>  {
51
52        #region constructors
53        internal ILBaseCell(ILCellStorage cellStorage, bool tempArr)
54            : base(cellStorage, tempArr) { }
55        #endregion constructors
56
57        #region properties
58        /// <summary>
59        /// Transposed version of this ILCell
60        /// </summary>
61        /// <remarks>This property is an alias for 'Shifted(1). </remarks>
62        /// <seealso cref="ILNumerics.ILBaseCell.Shifted(int)"/>
63        public new ILRetCell T {
64            get {
65                return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(1));
66            }
67        }
68        /// <summary>
69        /// Access to the more specialized version (ILCellStorage) of this storage
70        /// </summary>
71        internal new ILCellStorage Storage {
72            get { return (m_storage as ILCellStorage); }
73            set {
74                // e.g. Storage.Detach() may return itself (if no detaching is
75                // required). So we must check for that equalty here!
76                if (!object.Equals(value, m_storage)) {
77                    m_storage.Dispose();
78                    m_storage = value;
79                }
80            }
81        }
82        /// <summary>
83        /// Clone of this cell
84        /// </summary>
85        /// <remarks><para>
86        /// Clones of all arrays in ILNumerics.Server are done in a very fast, lazy way. This means,
87        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same
88        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays on write access.</para>
89        /// <para>Cells profit from the same efficient clone creation process. However, since a cell may store an arbitrarily deep
90        /// hirarchy of other cells and arrays, in order to clone a cell, the cells elements have to be cloned as well - in an
91        /// recursive manner. Clones play an important role for ILNumerics cells. They are used to implement value semantics for cell
92        /// elements. I.e.: the cloned cell returned cannot not be used to alter elements of the original cell in any way.</para></remarks>
93        public new ILRetCell C {
94            get {
95                return new ILRetCell((ILCellStorage)Storage.Clone());
96            }
97        }
98        #endregion
99
100        #region public interface
101        /// <summary>
102        /// Concatenate this cell
103        /// </summary>
104        /// <param name="A">Cell to concatenate this cell with</param>
105        /// <param name="dim">Dimension index along which to concatenate the cells.</param>
106        /// <returns>New cell with concatenation of all elements of both cells</returns>
107        /// <remarks>The array returned will be a copy of both cells involved.
108        /// If <paramref name="dim"/> is larger than
109        /// the number of dimensions of one of the arrays its value will be used in modulus.
110        /// <para>The resulting cell has the size of both input cells, laid beside one
111        /// another along the <paramref name="dim"/> dimension.</para></remarks>
112        public ILRetCell Concat(ILInCell A, int dim) {
113            using (ILScope.Enter(A))
114                return new ILRetCell((ILCellStorage)Storage.Concat(A.Storage, dim));
115        }
116        /// <summary>
117        /// Retrieve a single array of a known type from a cell position
118        /// </summary>
119        /// <typeparam name="T">Element type of the array</typeparam>
120        /// <param name="indices">Position of the array within this cell</param>
121        /// <returns>Lazy, shallow clone of the array found at the given position</returns>
122        public ILRetArray<T> GetArray<T>(params ILBaseArray[] indices) {
123            using (ILScope.Enter(indices))
124                return new ILRetArray<T>(Storage.GetDenseStorage<T>(indices));
125        }
126        /// <summary>
127        /// Retrieve a single element from the given position
128        /// </summary>
129        /// <param name="indices">Position of the element to retrieve, must evaluate to a scalar position</param>
130        /// <returns>A clone of the scalar element found</returns>
131        /// <remarks>
132        /// <para>The method returns a lazy, shallow clone of the content of the cell element specified by <paramref name="indices"/>.
133        /// However, the return type (<code>ILBaseArray</code>) is not strongly typed and may contain <b>any</b> element. According to the
134        /// true element stored in the cell, this might be an array of arbitrary type, null or even another cell. Moreover, handling
135        /// <code>ILBaseArray</code> directly is not recommended for ILNumerics, since this would hinder the memory management from proper
136        /// functioning. Therefore: <b>The use of this method is not recommended and left to ILNumerics experts - for very
137        /// specific and rare situations.</b></para>
138        /// </remarks>
139        internal ILBaseArray GetBaseArray(params ILBaseArray[] indices) {
140            using (ILScope.Enter(indices))
141                return Storage.GetScalar(indices);
142        }
143        /// <summary>
144        /// Retrieve a subcell of this cell
145        /// </summary>
146        /// <param name="indices">Subcell definition, arbitrary size</param>
147        /// <returns>A cell with a lazy, shallow clone of the elements of this cell, addressed by <paramref name="indices"/></returns>
148        /// <remarks>The cell returned will have the size and shape specified by <paramref name="indices"/>.</remarks>
149        public ILRetCell GetCell(params ILBaseArray[] indices) {
150            using (ILScope.Enter(indices)) {
151                ILCellStorage retStorage = (ILCellStorage)Storage.Subarray(indices);
152                if (retStorage.Size.NumberOfElements == 1) {
153                    ILCellStorage retInner = retStorage.GetValueTyped(0) as ILCellStorage;
154                    if (retInner == null)
155                        throw new Exceptions.ILArgumentException("no cell found at the specified position");
156                    return new ILRetCell(retInner);
157                } else {
158                    throw new Exceptions.ILArgumentException("index specification must resolve to a scalar element location");
159                }
160            }
161        }
162        /// <summary>
163        /// Enumerator returning elements as scalar cells
164        /// </summary>
165        /// <returns>Enumerator</returns>
166        /// <remarks>This method enables the use of cells in foreach loops.
167        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator
168        /// is compatible with ILNumerics memory management.</para></remarks>
169        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
170        /// foreach (double element in A) {
171        /// // all elements are scalar double values
172        /// String.Format("Element: {0} ",element);
173        /// // Note: 'element' cannot be used to alter the collection!
174        /// }
175        /// </code></example>
176        public new IEnumerator<ILRetCell> GetEnumerator() {
177            int len = Size.NumberOfElements;
178            for (int i = 0; i < len; i++) {
179                //yield return GetBaseArray(i);
180                yield return new ILRetCell((ILCellStorage)Storage.Subarray(i));
181            }
182        }
183        /// <summary>
184        /// Retrieve single element from this cell
185        /// </summary>
186        /// <param name="idx">Position of the element</param>
187        /// <returns>Lazy, shallow clone of the element to retrieve or null, if there is no element at this place</returns>
188        public new object GetValue(params int[] idx) {
189            return Storage.GetValue(idx);
190        }
191        /// <summary>
192        /// Retrieve a typed single element from within the cell, supports deep indexing
193        /// </summary>
194        /// <typeparam name="T">Expected type of the value to be returned</typeparam>
195        /// <param name="indices">Location of the single element addressed</param>
196        /// <returns>A clone of the single element addressed by <paramref name="indices"/></returns>
197        /// <remarks>The element returned will have the type given by <typeparamref name="T"/>. It is an error to specify
198        /// a different type as the true type of the element specified. An exception is thrown if both types differ.</remarks>
199        public T GetValue<T>(params int[] indices) {
200            return Storage.GetValue<T>(indices);
201        }
202        /// <summary>
203        /// Test if an element of the cell is an array of the given element type
204        /// </summary>
205        /// <typeparam name="T">The array element type to check the cell element against</typeparam>
206        /// <param name="position">Position of the cell element to be tested</param>
207        /// <returns>true if the element found at the given position is an array of the element type <typeparamref name="T"/>, false otherwise</returns>
208        /// <remarks>The method is helpful in order to investigate the contents of a cell array. If you are not sure about the
209        /// types of elements in the cell, this function can be used to make sure, elements are of the expected type before retrieving them as such.
210        /// <para>In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as
211        /// typeparameter <typeparamref name="T"/>. That means, in order to find out, if the first cell element stores an array of int (<code>ILArray&lt;int></code>),
212        /// one may use <code>cell.IsTypeOf&lt;int>(0)</code></para>
213        /// <para>In order to test, if a cell element is of type <code>ILCell</code>, one can provide the type <code>ILCell</code> as type parameter:
214        /// <code>cell.IsTypeOf&lt;ILCell>(0)</code>. Note the different semantic when checking for cell elements of type cell. Here we do not test for the
215        /// element type but for the array type itself, ie. <code>ILCell</code>. The reason of this is: the type of elements of <code>ILCell</code> is
216        /// an implementation detail and therefore hidden to the user.</para>
217        /// </remarks>
218        /// <example>
219        /// <para>In the following example a ILCell of size 3x2 is created. It stores several array types, among which other cells are stored as elements of the outer cell.</para>
220        /// <code>ILCell cell = ILMath.cell(new ILSize(3, 2)
221        ///                      , "first element"
222        ///                      , 2.0
223        ///                      , ILMath.cell(Math.PI, 100f)
224        ///                      , ILMath.create&lt;short>(1, 2, 3, 4, 5, 6)
225        ///                      , new double[] {-1.4, -1.5, -1.6});
226        /// </code>
227        /// The cell is now:
228        /// <code>ILCell [3,2]
229        ///          &lt;String>      first element  &lt;Int16> [2,3,4,5,6]
230        ///          &lt;Double>          2          ILCell [1,3]           
231        ///          ILCell [2,1]                                    (null)
232        /// </code>
233        /// We test the element type of every element in the cell:
234        /// <code>
235        /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf&lt;string>(0));
236        /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(0));
237        ///                                     
238        /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(1));
239        /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(2));
240        ///                                                                         
241        /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf&lt;short>(0, 1));
242        /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(1, 1));
243        /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf&lt;double>(2, 1));
244        /// </code>
245        /// This gives the following output:
246        /// <code>
247        /// cell[0,0] is element type 'string': True
248        /// cell[0,0] is element type 'double': False
249        /// cell[1,0] is element type 'double': True
250        /// cell[2,0] is element type 'ILCell': True
251        /// cell[0,1] is element type 'short': True
252        /// cell[1,1] is element type 'ILCell': True
253        /// cell[2,1] is element type 'double': False  // element is null, IsTypeOf&lt;> never gives true
254        /// </code></example>
255        public bool IsTypeOf<T>(params ILBaseArray[] position) {
256            using (ILScope.Enter(position))
257                return Storage.IsTypeOf<T>(position);
258        }
259        /// <summary>
260        /// Create reshaped copy of this cell
261        /// </summary>
262        /// <param name="size">New size of the cell</param>
263        /// <returns>Reshaped copy of the cell</returns>
264        /// <remarks><para>The current instance will not be changed! A new cell is created, having
265        /// the elements of this cell and a shape as determined by <paramref name="size"/>.</para>
266        /// </remarks>
267        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in
268        /// <paramref name="size"/> do not match the number of elements in this cell.</exception>
269        public new ILRetCell Reshape(ILSize size) {
270            ILCell ret = C;
271            ret.Storage.Reshape(size);
272            return ret;
273        }
274        /// <summary>
275        /// Create reshaped copy of this cell
276        /// </summary>
277        /// <param name="size">New size of the cell</param>
278        /// <returns>Reshaped copy of the cell</returns>
279        /// <remarks><para>The current instance will not be changed! A new cell is created, having
280        /// the elements of this cell and a shape as determined by <paramref name="size"/>.</para>
281        /// </remarks>
282        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in
283        /// <paramref name="size"/> do not match the number of elements in this cell.</exception>
284        public new ILRetCell Reshape(params int[] size) {
285            return Reshape(new ILSize(size));
286        }
287        /// <summary>
288        /// Create replication of this cell
289        /// </summary>
290        /// <param name="dims">Size descriptor
291        /// <remarks>If the number of elements in <paramref name="dims"/> is
292        /// less than the number of dimensions in this cell, the trailing dimensions will
293        /// be set to 1 (singleton dimensions). On the other hand, if the number specified
294        /// is larger then the number of dimension stored inside the storge the resulting
295        /// storage will get its number of dimensions extended accordingly. </param></remarks>
296        /// <returns>Array created by multiple replications of this array along
297        /// arbitrary dimensions according to <paramref name="dims"/></returns>
298        public new ILRetCell Repmat(params int[] dims) {
299            return new ILRetCell((ILCellStorage)Storage.Repmat(dims));
300        }       
301        /// <summary>
302        /// Dimension shifted cell from this cell
303        /// </summary>
304        /// <param name="shift">Number of dimensions to shift</param>
305        /// <returns>Shifted version of this cell</returns>
306        /// <remarks><para>The shift is done 'to the left':</para>
307        /// <example><code>ILCell A = cell(2,4); <br/>
308        /// ILCell B = A.Shifted(1); <br/>
309        /// // B is now: ILCell [4,2] <br/>
310        /// // <br/>
311        /// ILCell C = cell(2,4,3);<br/>
312        /// ILCell D = C.Shifted(1); <br/>
313        /// // D is now: ILCell [4,3,2] <br/>
314        /// </code></example>
315        /// <para>The dimensions are shifted circulary to the left. This
316        /// can be imagined as removing the first dimensions from the beginning of the list of
317        /// dimensions and "append" them to the end in a ringbuffer style. </para>
318        /// <para>For dimension shifts of '1', you may consider using the
319        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
320        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
321        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
322        public new ILRetCell Shifted(int shift) {
323            return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(shift));
324        }
325        /// <summary>
326        /// Subarray access. Get/set regular subarray.
327        /// </summary>
328        /// <param name="indices">Address range</param>
329        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
330        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you
331        /// may ommit those trailing dimensions in <c>indices</c>.
332        /// <para>The indexer may be used for querying or altering single/any elements
333        /// in this cell. <c>indices</c> may contains index specifications for one to any
334        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
335        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by
336        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the
337        /// values returned will not alter the original elements.</para>
338        /// <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>
339        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any
340        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be
341        /// merged and the array will be reshaped before applying the removal to it.
342        /// <example>
343        /// <code>
344        /// ILCell C = new ILCell(4,10);
345        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
346        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
347        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full!
348        /// </code></example></para>
349        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
350        /// </remarks>
351        public new ILRetCell Subarray(params ILBaseArray[] indices) {
352            using (ILScope.Enter(indices)) {
353                ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
354                return new ILRetCell(elements);
355            }
356        }
357        #endregion
358
359    }
360}
Note: See TracBrowser for help on using the repository browser.