Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetCell.cs @ 12283

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

#1967: ILNumerics source for experimentation

File size: 46.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.Collections.Generic;
42using System.IO;
43using ILNumerics.Exceptions;
44using ILNumerics.Storage;
45
46namespace ILNumerics {
47    /// <summary>
48    /// ILCell: container class holding arbitrary array objects
49    /// </summary>
50    /// <remarks>
51    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type.
52    /// </remarks>
53    public sealed class ILRetCell : ILBaseCell {
54
55        private static readonly bool s_isTempArray = true;
56
57        #region constructors
58        /// <summary>
59        /// Create cell object with pre-created data in specified dimensions
60        /// </summary>
61        /// <param name="data">Predefined element data array, will be used for new cell (no copy will be made)</param>
62        /// <param name="size">Size of the new cell</param>
63        /// <remarks>Object array data will directly be used for storage. No
64        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
65        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
66        internal ILRetCell(ILStorage[] data, params int[] size)
67            : base(new ILCellStorage(data, new ILSize(size)), s_isTempArray) {
68        }
69        /// <summary>
70        /// Create cell object with pre-created data in specified dimensions
71        /// </summary>
72        /// <param name="data">Predefined element data array, will be used for new cell (no copy will be made)</param>
73        /// <param name="size">Size of the new cell</param>
74        /// <remarks>Object array data will directly be used for storage. No
75        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
76        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
77        internal ILRetCell(ILStorage[] data, ILSize size)
78            : base(new ILCellStorage(data, size), s_isTempArray) {
79        }
80        /// <summary>
81        /// Create new cell object, elements will be 'null'
82        /// </summary>
83        /// <param name="size">Size descriptor of the new cell</param>
84        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
85        internal ILRetCell(params int[] size)
86            : base(new ILCellStorage(new ILStorage[ILCell.prod(size)], new ILSize(size)), s_isTempArray) { }
87
88        internal ILRetCell(ILCellStorage cellStorage)
89            : base(cellStorage, s_isTempArray) { }
90
91        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
92        internal ILRetCell(ILSize size, params ILStorage[] values)
93            : base(new ILCellStorage(values, size), s_isTempArray) { }
94
95        #endregion constructors
96
97        #region properties
98        /// <summary>
99        /// Clone of this cell
100        /// </summary>
101        /// <remarks><para>
102        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means,
103        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same
104        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays on write access.</para>
105        /// <para>Cells profit from the same efficient clone creation process. However, since a cell may store an arbitrarily deep
106        /// hierarchy of other cells and arrays, in order to clone a cell, the cell elements have to be cloned as well - in an
107        /// recursive manner. Clones play an important role for ILNumerics cells. They are used to implement value semantics for cell
108        /// elements. I.e.: the cloned cell returned cannot not be used to alter elements of the original cell in any way.</para></remarks>
109        public new ILRetCell C {
110            get {
111                return this;
112            }
113        }
114        /// <summary>
115        /// Size descriptor shortcut
116        /// </summary>
117        public override ILSize S {
118            get {
119                using (ILScope.Enter(this))
120                    return Storage.Size;
121            }
122        }
123        /// <summary>
124        /// Size descriptor
125        /// </summary>
126        public override ILSize Size {
127            get {
128                using (ILScope.Enter(this))
129                    return Storage.Size;
130            }
131        }
132        /// <summary>
133        /// Test if this array instance is a column vector
134        /// </summary>
135        public override bool IsColumnVector {
136            get {
137                using (ILScope.Enter(this))
138                    return Size[1] == 1 && Size.NumberOfDimensions == 2; ;
139            }
140        }
141        /// <summary>
142        /// Test if this array instance is a row vector
143        /// </summary>
144        public override bool IsRowVector {
145            get {
146                using (ILScope.Enter(this))
147                    return Size[0] == 1 && Size.NumberOfDimensions == 2;
148            }
149        }
150        /// <summary>
151        /// Determine if this array has complex elements.
152        /// </summary>
153        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
154        public override bool IsComplex {
155            get {
156                using (ILScope.Enter(this))
157                    return base.IsComplex;
158            }
159        }
160        /// <summary>
161        /// Test if this instance is an empty array (number of elements stored = 0)
162        /// </summary>
163        public override bool IsEmpty {
164            get {
165                using (ILScope.Enter(this))
166                    return Size.NumberOfElements == 0;
167            }
168        }
169        /// <summary>
170        /// Test if this instance is a matrix
171        /// </summary>
172        /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b>
173        /// dimensions must equal 2. This attribute is readonly.</remarks>
174        public override bool IsMatrix {
175            get {
176                using (ILScope.Enter(this))
177                    return Size.NumberOfDimensions == 2;
178            }
179        }
180        /// <summary>
181        /// Determine if this array holds numeric values.
182        /// </summary>
183        /// <remarks>An ILArray is numeric as long as its elements are one of the
184        /// following types:
185        /// <list type="table">
186        /// <listheader>
187        ///     <term>inner type</term>
188        /// </listheader>
189        /// <item>
190        ///     <term>System.double</term>
191        ///     <description>floating point, real, 8 bytes </description>
192        /// </item>
193        /// <item>
194        ///     <term>System.float</term>
195        ///     <description>floating point real, 4 bytes</description>
196        /// </item>
197        /// <item>
198        ///     <term>ILNumerics.complex</term>
199        ///     <description>floating point complex, 16 bytes</description>
200        /// </item>
201        /// <item>
202        ///     <term>ILNumerics.fcomplex</term>
203        ///     <description>floating point complex, 8 bytes</description>
204        /// </item>
205        /// <item>
206        ///     <term>System.char</term>
207        ///     <description>integer, real, 1 byte</description>
208        /// </item>
209        /// <item>
210        ///     <term>System.byte</term>
211        ///     <description>integer, real, 1 byte</description>
212        /// </item>
213        /// <item>
214        ///     <term>System.Int16</term>
215        ///     <description>integer, real, 2 byte</description>
216        /// </item>
217        /// <item>
218        ///     <term>System.Int32</term>
219        ///     <description>integer, real, 4 byte</description>
220        /// </item>
221        /// <item>
222        ///     <term>System.Int64</term>
223        ///     <description>integer, real, 8 byte</description>
224        /// </item>
225        /// <item>
226        ///     <term>System.UInt16</term>
227        ///     <description>unsigned integer, real, 2 byte</description>
228        /// </item>
229        /// <item>
230        ///     <term>System.UInt32</term>
231        ///     <description>unsigned integer, real, 4 byte</description>
232        /// </item>
233        /// <item>
234        ///     <term>System.UInt64</term>
235        ///     <description>unsigned integer, real, 8 byte</description>
236        /// </item>
237        /// </list>
238        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
239        /// </remarks>
240        public override bool IsNumeric {
241            get {
242                using (ILScope.Enter(this))
243                    return base.IsNumeric;
244            }
245        }
246        /// <summary>
247        /// Test if this instance is a scalar
248        /// </summary>
249        /// <remarks>This attribute is readonly. It returns: Dimension.NumberOfElements == 1.</remarks>
250        public override bool IsScalar {
251            get {
252                using (ILScope.Enter(this))
253                    return Size.NumberOfElements == 1;
254            }
255        }
256        /// <summary>
257        /// Test if this array is a vector
258        /// </summary>
259        /// <remarks>In order for an array to be a vector the number of <b>non singleton</b>
260        /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore
261        /// it is not sufficient to test for the number of dimensions, but to take the number of
262        /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
263        public override bool IsVector {
264            get {
265                using (ILScope.Enter(this))
266                    return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
267            }
268        }
269        /// <summary>
270        /// Length of the longest dimension of this instance
271        /// </summary>
272        /// <remarks>This property is readonly.
273        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
274        public override int Length {
275            get {
276                using (ILScope.Enter(this))
277                    return base.Length;
278            }
279        }
280        /// <summary>
281        /// Transposed version of this ILCell
282        /// </summary>
283        public new ILRetCell T {
284            get {
285                using (ILScope.Enter(this))
286                    return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(1));
287            }
288        }
289        /// <summary>
290        /// Gets the name of this array (readonly)
291        /// </summary>
292        public new String Name {
293            get {
294                using (ILScope.Enter(this))
295                    return m_name;
296            }
297        }
298        /// <summary>
299        /// Access to the more specialized version (ILCellStorage) of this storage
300        /// </summary>
301        internal new ILCellStorage Storage {
302            get { return (m_storage as ILCellStorage); }
303            set {
304                // e.g. Storage.Detach() may return itself (if no detaching is
305                // required). So we must check for that equalty here!
306                if (!object.Equals(value, m_storage)) {
307                    m_storage.Dispose();
308                    m_storage = value;
309                }
310            }
311        }
312        #endregion
313
314        #region implicit casts
315        #region constructional operators
316        /// <summary>
317        /// Convert primitive integer to a scalar temporary cell
318        /// </summary>
319        /// <param name="value">Primitive scalar int value</param>
320        /// <returns>New scalar temporary cell</returns>
321        public static implicit operator ILRetCell(int value) {
322            ILRetCell ret = createScalar(value);
323            ret.Storage.FromImplicitCast = true;
324            return ret;
325        }
326        /// <summary>
327        /// Convert primitive double to a scalar temporary cell
328        /// </summary>
329        /// <param name="value">Primitive scalar double value</param>
330        /// <returns>New scalar temporary cell</returns>
331        public static implicit operator ILRetCell(double value) {
332            ILRetCell ret = createScalar(value);
333            ret.Storage.FromImplicitCast = true;
334            return ret;
335        }
336        /// <summary>
337        /// Convert primitive float to a scalar temporary cell
338        /// </summary>
339        /// <param name="value">Primitive scalar float value</param>
340        /// <returns>New scalar temporary cell</returns>
341        public static implicit operator ILRetCell(float value) {
342            ILRetCell ret = createScalar(value);
343            ret.Storage.FromImplicitCast = true;
344            return ret;
345        }
346        /// <summary>
347        /// Convert primitive byte to a scalar temporary cell
348        /// </summary>
349        /// <param name="value">Primitive byte int value</param>
350        /// <returns>New scalar temporary cell</returns>
351        public static implicit operator ILRetCell(byte value) {
352            ILRetCell ret = createScalar(value);
353            ret.Storage.FromImplicitCast = true;
354            return ret;
355        }
356        /// <summary>
357        /// Encapsulate integer System.Array into a scalar temporary cell
358        /// </summary>
359        /// <param name="value">Primitive System.Int32 value - no copy will be made!</param>
360        /// <returns>New scalar temporary cell</returns>
361        public static implicit operator ILRetCell(int[] value) {
362            ILRetCell ret = createArray(value);
363            ret.Storage.FromImplicitCast = true;
364            return ret;
365        }
366        /// <summary>
367        /// Convert string to a scalar temporary cell
368        /// </summary>
369        /// <param name="value">String value</param>
370        /// <returns>New scalar temporary cell</returns>
371        public static implicit operator ILRetCell(string value) {
372            ILRetCell ret = createScalar(value);
373            ret.Storage.FromImplicitCast = true;
374            return ret;
375        }
376        /// <summary>
377        /// Encapsulate array of strings into a scalar temporary cell
378        /// </summary>
379        /// <param name="value">String array - no copy will be made!</param>
380        /// <returns>New scalar temporary cell</returns>
381        public static implicit operator ILRetCell(string[] value) {
382            ILRetCell ret = createArray(value);
383            ret.Storage.FromImplicitCast = true;
384            return ret;
385        }
386        #endregion
387
388        #region conversional operators
389        /// <summary>
390        /// Convert cell to temporary cell
391        /// </summary>
392        /// <param name="A">Cell</param>
393        /// <returns>Temporary cell</returns>
394        public static implicit operator ILRetCell(ILCell A) {
395            if (object.Equals(A, null)) return null;
396            return A.C;
397        }
398        /// <summary>
399        /// Convert input parameter cell to temporary cell
400        /// </summary>
401        /// <param name="A">Input parameter cell</param>
402        /// <returns>Temporary cell</returns>
403        public static implicit operator ILRetCell(ILInCell A) {
404            if (object.Equals(A, null)) return null;
405            return A.C;
406        }
407        /// <summary>
408        /// Convert output parameter cell to temporary cell
409        /// </summary>
410        /// <param name="A">Output parameter cell</param>
411        /// <returns>Temporary cell</returns>
412        public static implicit operator ILRetCell(ILOutCell A) {
413            if (object.Equals(A, null)) return null;
414            return A.C;
415        }
416        /// <summary>
417        /// Wrap single logical array into a new scalar temporary cell
418        /// </summary>
419        /// <param name="A">Logical array</param>
420        /// <returns>Scalar cell</returns>
421        public static implicit operator ILRetCell(ILBaseLogical A) {
422            if (object.Equals(A, null)) return null;
423            ILRetCell ret = ILMath.cell(A);
424            ret.Storage.FromImplicitCast = true;
425            return ret;
426        }
427        #endregion
428        #endregion
429
430        #region helper functions
431        private static ILRetCell createScalar<T>(T value) {
432            using (ILScope.Enter()) {
433                ILCell ret = new ILCell(1, 1);
434                ret.SetValue(new ILDenseStorage<T>(new T[] { value }, ILSize.Scalar1_1), 0, 0);
435                return ret;
436            }
437        }
438        private static ILRetCell createArray<T>(T[] value) {
439            using (ILScope.Enter()) {
440                ILCell ret = new ILCell(1, 1);
441                ret.SetValue(new ILDenseStorage<T>(value, new ILSize(1, value.Length)), 0, 0);
442                return ret;
443            }
444        }
445        #endregion helper functions
446
447        #region public interface
448        /// <summary>
449        /// Clone of this array
450        /// </summary>
451        /// <remarks><para>
452        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means,
453        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same
454        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays
455        /// on write access.</para>
456        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
457        internal override ILBaseArray Clone() {
458            return this;
459        }
460        /// <summary>
461        /// Concatenate this cell
462        /// </summary>
463        /// <param name="A">Cell to concatenate this cell with</param>
464        /// <param name="dim">Dimension index along which to concatenate the cells.</param>
465        /// <returns>new cell with concatenation of all elements of both cells</returns>
466        /// <remarks>The array returned will be a copy of both cells involved.
467        /// If <paramref name="dim"/> is larger than
468        /// the number of dimensions of one of the arrays its value will be used in modulus.
469        /// <para>The resulting cell has the size of both input cells, laid beside one
470        /// another along the <paramref name="dim"/> dimension.</para></remarks>
471        public new ILRetCell Concat(ILInCell A, int dim) {
472            using (ILScope.Enter(this))
473            using (ILScope.Enter(A))
474                return base.Concat(A, dim);
475        }
476        /// <summary>
477        /// Compare elements and shape of this array with another array
478        /// </summary>
479        /// <param name="A">Other array</param>
480        /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
481        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays.</para></remarks>
482        public override bool Equals(object A) {
483            using (ILScope.Enter(this))
484                return base.Equals(A);
485        }
486        /// <summary>
487        /// Copy values of all elements into System.Array.
488        /// </summary>
489        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
490        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and
491        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements,
492        /// it will be recreated from the ILNumerics memory pool.</remarks>
493        internal new void ExportValues(ref ILStorage[] outArray) {
494            using (ILScope.Enter(this))
495                Storage.ExportValues(ref outArray);
496        }
497        /// <summary>
498        /// Retrieve a single array of a known type from a cell position
499        /// </summary>
500        /// <typeparam name="T">Element type of the array</typeparam>
501        /// <param name="indices">Position of the array within this cell</param>
502        /// <returns>Lazy, shallow clone of the array found at the given position</returns>
503        public new ILRetArray<T> GetArray<T>(params ILBaseArray[] indices) {
504            using (ILScope.Enter(this))
505            using (ILScope.Enter(indices))
506                return base.GetArray<T>(indices);
507        }
508        /// <summary>
509        /// Retrieve a single element from the given position
510        /// </summary>
511        /// <param name="indices">Position of the element to retrieve, must evaluate to a scalar position</param>
512        /// <returns>A clone of the scalar element found</returns>
513        /// <remarks>
514        /// <para>The method returns a lazy, shallow clone of the content of the cell element specified by <paramref name="indices"/>.
515        /// However, the return type (<code>ILBaseArray</code>) is not strongly typed and may contain <b>any</b> element. According to the
516        /// true element stored in the cell, this might be an array of arbitrary type, null or even another cell. Moreover, handling
517        /// <code>ILBaseArray</code> directly is not recommended for ILNumerics, since this would hinder the memory management from proper
518        /// functioning. Therefore: <b>The use of this method is not recommended and left to ILNumerics experts - for very
519        /// specific and rare situations.</b></para>
520        /// </remarks>
521        public new ILBaseArray GetBaseArray(params ILBaseArray[] indices) {
522            using (ILScope.Enter(this))
523            using (ILScope.Enter(indices))
524                return base.GetBaseArray(indices);
525        }
526        /// <summary>
527        /// Retrieve a subcell of this cell
528        /// </summary>
529        /// <param name="indices">Subcell definition, arbitrary size</param>
530        /// <returns>A cell with a lazy, shallow clone of the elements of this cell, addressed by <paramref name="indices"/></returns>
531        /// <remarks>The cell returned will have the size and shape specified by <paramref name="indices"/>.</remarks>
532        public new ILRetCell GetCell(params ILBaseArray[] indices) {
533            using (ILScope.Enter(this))
534            using (ILScope.Enter(indices)) {
535                return new ILRetCell((ILCellStorage)Storage.Subarray(indices));
536            }
537        }
538        /// <summary>
539        /// Enumerator returning elements as scalar cells
540        /// </summary>
541        /// <returns>Enumerator</returns>
542        /// <remarks>This method enables the use of cells in foreach loops.
543        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator
544        /// is compatible with ILNumerics memory management.</para></remarks>
545        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
546        /// foreach (double element in A) {
547        /// // all elements are scalar double values
548        /// String.Format("Element: {0} ",element);
549        /// // Note: 'element' cannot be used to alter the collection!
550        /// }
551        /// </code></example>
552        public new IEnumerator<ILRetCell> GetEnumerator() {
553            using (ILScope.Enter(this)) {
554                return base.GetEnumerator();
555            }
556        }
557        /// <summary>
558        /// Generate a hash code based on the current arrays values
559        /// </summary>
560        /// <returns>Hash code</returns>
561        /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
562        /// Therefore, the function must iterate over all elements in the array - which makes it somehow a costly
563        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries
564        /// or hashtables, which make great use of hash codes.
565        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
566        public override int GetHashCode() {
567            using (ILScope.Enter(this))
568                return base.GetHashCode();
569        }
570        /// <summary>
571        /// Get minimum and maximum value of all elements - if any
572        /// </summary>
573        /// <param name="min">[Output] Minimum value</param>
574        /// <param name="max">[Output] Maximum value</param>
575        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
576        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
577        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
578        internal new bool GetLimits(out ILStorage min, out ILStorage max) {
579            using (ILScope.Enter(this))
580                return base.GetLimits(out min, out max);
581        }
582        /// <summary>
583        /// Retrieve single element from this cell
584        /// </summary>
585        /// <param name="idx">Position of the element</param>
586        /// <returns>Lazy, shallow clone of the element to retrieve or null, if there is no element at this place</returns>
587        public new object GetValue(params int[] idx) {
588            using (ILScope.Enter(this)) {
589                return base.GetValue(idx);
590            }
591        }
592        /// <summary>
593        /// Retrieve a typed single element from within the cell, supports deep indexing
594        /// </summary>
595        /// <typeparam name="T">Expected type of the value to be returned</typeparam>
596        /// <param name="indices">Location of the single element addressed</param>
597        /// <returns>A clone of the single element addressed by <paramref name="indices"/></returns>
598        /// <remarks>The element returned will have the type given by <typeparamref name="T"/>. It is an error to specify
599        /// a different type as the true type of the element specified. An exception is thrown if both types differ.</remarks>
600        public new T GetValue<T>(params int[] indices) {
601            using (ILScope.Enter(this)) {
602                return Storage.GetValue<T>(indices);
603            }
604        }
605        /// <summary>
606        /// Test if an element of the cell is an array of the given element type
607        /// </summary>
608        /// <typeparam name="T">The array element type to check the cell element against</typeparam>
609        /// <param name="position">Position of the cell element to be tested</param>
610        /// <returns>true if the element found at the given position is an array of the element type <typeparamref name="T"/>, false otherwise</returns>
611        /// <remarks>The method is helpful in order to investigate the contents of a cell array. If you are not sure about the
612        /// 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.
613        /// <para>In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as
614        /// 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>),
615        /// one may use <code>cell.IsTypeOf&lt;int>(0)</code></para>
616        /// <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:
617        /// <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
618        /// 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
619        /// an implementation detail and therefore hidden to the user.</para>
620        /// </remarks>
621        /// <example>
622        /// <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>
623        /// <code>ILCell cell = ILMath.cell(new ILSize(3, 2)
624        ///                      , "first element"
625        ///                      , 2.0
626        ///                      , ILMath.cell(Math.PI, 100f)
627        ///                      , ILMath.create&lt;short>(1, 2, 3, 4, 5, 6)
628        ///                      , new double[] {-1.4, -1.5, -1.6});
629        /// </code>
630        /// The cell is now:
631        /// <code>ILCell [3,2]
632        ///          &lt;String>      first element  &lt;Int16> [2,3,4,5,6]
633        ///          &lt;Double>          2          ILCell [1,3]           
634        ///          ILCell [2,1]                                    (null)
635        /// </code>
636        /// We test the element type of every element in the cell:
637        /// <code>
638        /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf&lt;string>(0));
639        /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(0));
640        ///                                     
641        /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(1));
642        /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(2));
643        ///                                                                         
644        /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf&lt;short>(0, 1));
645        /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(1, 1));
646        /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf&lt;double>(2, 1));
647        /// </code>
648        /// This gives the following output:
649        /// <code>
650        /// cell[0,0] is element type 'string': True
651        /// cell[0,0] is element type 'double': False
652        /// cell[1,0] is element type 'double': True
653        /// cell[2,0] is element type 'ILCell': True
654        /// cell[0,1] is element type 'short': True
655        /// cell[1,1] is element type 'ILCell': True
656        /// cell[2,1] is element type 'double': False  // element is null, IsTypeOf&lt;> never gives true
657        /// </code></example>
658        public new bool IsTypeOf<T>(params ILBaseArray[] position) {
659            using (ILScope.Enter(this))
660            using (ILScope.Enter(position)) {
661                return Storage.IsTypeOf<T>(position);
662            }
663        }
664        /// <summary>
665        /// Create replication of this cell
666        /// </summary>
667        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is
668        /// less than the number of dimensions in this cell, the trailing dimensions will
669        /// be set to 1 (singleton dimensions). On the other hand, if the number specified
670        /// is larger then the number of dimension stored inside the storge the resulting
671        /// storage will get its number of dimensions extended accordingly. </param>
672        /// <returns>Array being created by multiple replications of this array along
673        /// arbitrary dimensions according to <paramref name="dims"/></returns>
674        public new ILRetCell Repmat(params int[] dims) {
675            using (ILScope.Enter(this))
676                return new ILRetCell((ILCellStorage)Storage.Repmat(dims));
677        }
678        /// <summary>
679        /// Create reshaped copy of this cell
680        /// </summary>
681        /// <param name="dimensions">New dimensions of the cell</param>
682        /// <returns>Reshaped copy of the cell</returns>
683        /// <remarks><para>The current instance will not be changed! A new cell is created, having
684        /// the elements of this cell and a shape as determined by <paramref name="dimensions"/>.</para>
685        /// </remarks>
686        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in
687        /// <paramref name="dimensions"/> do not match the number of elements in this cell.</exception>
688        public new ILRetCell Reshape(ILSize dimensions) {
689            using (ILScope.Enter(this)) {
690                return base.Reshape(dimensions);
691            }
692        }
693        /// <summary>
694        ///  Serialize this ILArray into a binary stream.
695        /// </summary>
696        /// <param name="outStream">System.IO.Stream to receive the byte stream
697        /// for this ILBaseArray</param>
698        /// <returns>True on success, false on error.</returns>
699        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
700        /// </remarks>
701        public override bool Serialize(Stream outStream) {
702            using (ILScope.Enter(this))
703                return base.Serialize(outStream);
704        }
705        /// <summary>
706        /// Dimension shifted cell from this cell
707        /// </summary>
708        /// <param name="shift">Number of dimensions to shift</param>
709        /// <returns>Shifted version of this cell</returns>
710        /// <remarks><para>The shift is done 'to the left':</para>
711        /// <example><code>ILCell A = cell(2,4);
712        /// ILCell B = A.Shifted(1);
713        /// // B is now: ILCell [4,2]
714        ///
715        /// ILCell C = cell(2,4,3);
716        /// ILCell D = C.Shifted(1);
717        /// // D is now: ILCell [4,3,2]
718        /// </code></example>
719        /// <para>The dimensions are shifted circulary to the left. This
720        /// can be imagined as removing the first dimensions from the beginning of the list of
721        /// dimensions and "append" them to the end in a ringbuffer style. </para>
722        /// <para>For dimension shifts of '1', you may consider using the
723        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
724        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
725        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
726        public new ILRetCell Shifted(int shift) {
727            using (ILScope.Enter(this))
728                return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(shift));
729        }
730        /// <summary>
731        /// Subarray access (readonly)
732        /// </summary>
733        /// <param name="indices">Address range</param>
734        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
735        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you
736        /// may ommit those trailing dimensions in <c>indices</c>.
737        /// <para>The indexer may be used for querying or altering single/any elements
738        /// in this cell. <c>indices</c> may contains index specifications for one to any
739        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
740        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by
741        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the
742        /// values returned will not alter the original elements stored in the cell.</para>
743        /// </remarks>
744        public new ILRetCell Subarray(params ILBaseArray[] indices) {
745            using (ILScope.Enter(this))
746            using (ILScope.Enter(indices)) {
747                ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
748                return new ILRetCell(elements);
749            }
750        }
751        /// <summary>
752        /// Send values of this instance to stream
753        /// </summary>
754        /// <param name="stream">Stream to write the values into.</param>
755        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
756        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
757        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
758        /// the values will be serialized.</param>
759        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s)
760        /// will be replaced from the format string before applying to the elements. This is done to
761        /// prevent the format from breaking the 'page' style of the output.</para>
762        /// <para>Writing cells to *.mat files is NOT SUPPORTED yet! </para></remarks>
763        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
764            using (ILScope.Enter(this))
765                try {
766                    int len;
767                    switch (method) {
768                        case ILArrayStreamSerializationFlags.Serial:
769                            len = Size.NumberOfElements;
770                            using (TextWriter tw = new StreamWriter(stream)) {
771                                for (int i = 0; i < len; i++) {
772                                    tw.Write(format, GetValue(i));
773                                }
774                            }
775                            break;
776                        case ILArrayStreamSerializationFlags.Formatted:
777                            format = format.Replace(Environment.NewLine, "");
778                            ILDenseStorage<ILStorage> temp = this.Storage.ShiftDimensions(1);
779                            //len = Dimensions.NumberOfElements / Dimensions[1];
780                            using (TextWriter tw = new StreamWriter(stream)) {
781                                tw.Write(temp.ValuesToString(0));
782                            }
783                            break;
784                        case ILArrayStreamSerializationFlags.Matlab:
785                            ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
786                            mf.Write(stream);
787                            break;
788                    }
789                } catch (Exception e) {
790                    throw new ILException("ToStream: Could not serialize to stream.", e);
791                }
792        }
793        #endregion
794
795        #region Index access
796        /// <summary>
797        /// Get/set/remove single element
798        /// </summary>
799        /// <paramref name="indices" value="Index to element"/>
800        /// <value>Inner element, new inner element or null</value>
801        /// <remarks>The type of access depends on the length of indices. If indices contains only one element,
802        /// the array will be accessed via sequential index access. This is sometimes called referred to as 'linear'
803        /// index addressing.
804        /// Sequential index access reflects the index of internal storage the way the data are actually organized
805        /// in memory. This access method is mainly convinient for vectors where you are not interested of orientation.
806        /// The following example demonstrates sequential index access for ILArray's (which also holds for ILCells):
807        /// <example><code>
808        /// ILArray&lt;double&gt; A = ILMath.counter(1,12);
809        /// A[2] gives: 3.0
810        /// </code>But the transpose
811        /// <code>
812        /// A.T[2] gives also: 3.0
813        /// </code>
814        /// For matrices and N-dimensional arrays this holds as well:
815        /// <code>
816        /// ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,3,2,2);
817        /// A =
818        /// [1.0 4.0
819        ///  2.0 5.0
820        ///  3.0 6.0
821        ///
822        ///  7.0 10.0
823        ///  8.0 11.0
824        ///  9.0 12.0]
825        ///
826        /// A = ILMath.Reshape(A,3,2,2);
827        /// A[10] gives 11.0
828        /// A[10,1] gives ILArgumentException -> out of range
829        /// A[2,1,1] gives 12.0
830        /// A[2,1] gives 6.0 (set trailing dimension to '0')</code></example>
831        /// <para>If the element addressed is a ILCell itself, a deep reference to this element will be returned instead.
832        /// I.e. all elements of the ILCell will be recursively replaced with references to itself. Therefore, altering the
833        /// elements returned will not alter the elements contained in the cell.</para>
834        /// <para>
835        /// <list type="bullet">
836        /// <listheader>The type of the element returned depends on the type of the element addressed:</listheader>
837        /// <item>For ILArray&lt;ElementType&gt; the array returned will be a clone of the original array.</item>
838        /// <item>For ILCell the ILBaseArray returned is a deep reference of the original elements stored.</item>
839        /// <item>For other types the behavior is undefined. (since other types are not implemented yet ;)</item>
840        /// </list> </para>
841        /// <para>This indexer may also be used for direct access to inner elements of (elements of elements of ...) this cell:
842        /// <example>
843        /// <code>
844        /// ILCell innerCell = new ILCell(2,1);
845        /// innerCell[0] = ILMath.vec(10,200);
846        /// innerCell[1] = new int[] {-10,-20,-30};
847        /// ILCell cell = new ILCell(2,1);
848        /// cell[0] = innerCell;
849        /// cell[1] = new string[] {"foobla"};
850        /// // cell is now:
851        /// // [ILCell,(1x2)]
852        /// //      [innerCell[0], ILArray&lt;double&gt;(1x181)]
853        /// //      [innerCell[0], ILArray&lt;double&gt;(1x3)]
854        /// // [ILArray&lt;string&gt;,(1x1)]
855        ///
856        /// cell[0,0] -&gt; will give innerCell eq. ILCell (1x2)
857        /// cell[0,1] -&gt; will give ILArray&lt;string&gt;
858        /// cell[0,0,0,1] -&gt; will give innerCell[1] eq. ILArray&lt;int&gt;(1x3)
859        /// </code>
860        /// </example>
861        /// In the last example above the trailing indices specified make the indexer walk down into the ILCell element and retrieve
862        /// the content of this element. This kind of index access may be done as deep as you want. Just
863        /// append the inner indices into inner elements to the right side of index specification. Addressing inner elements
864        /// this way is the only way to alter elements <b>directly</b> inside the ILCell. </para></remarks>
865        public ILRetCell this[params int[] indices] {
866            get {
867                using (ILScope.Enter(this)) {
868                    ILStorage val = Storage.GetValueTyped(indices);
869                    if (val is ILCellStorage)
870                        return new ILRetCell((ILCellStorage)val);
871                    else
872                        return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
873                }
874            }
875        }
876
877        /// <summary>
878        /// Subarray access. Get/set regular subarray.
879        /// </summary>
880        /// <param name="indices">Address range</param>
881        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
882        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you
883        /// may ommit those trailing dimensions in <c>indices</c>.
884        /// <para>The indexer may be used for querying or altering single/any elements
885        /// in this cell. <c>indices</c> may contains index specifications for one to any
886        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
887        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by
888        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the
889        /// values returned will not alter the original elements.</para>
890        /// <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>
891        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any
892        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be
893        /// merged and the array will be reshaped before applying the removal to it.
894        /// <example>
895        /// <code>
896        /// ILCell C = new ILCell(4,10);
897        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
898        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
899        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full!
900        /// </code></example></para>
901        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
902        /// </remarks>
903        public ILRetCell this[params ILBaseArray[] indices] {
904            get {
905                using (ILScope.Enter(this))
906                using (ILScope.Enter(indices)) {
907                    return Subarray(indices);
908                }
909            }
910        }
911
912        #endregion index access
913
914    }
915}
Note: See TracBrowser for help on using the repository browser.