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 |
|
---|
40 | using System;
|
---|
41 | using System.Collections.Generic;
|
---|
42 | using System.IO;
|
---|
43 | using ILNumerics.Exceptions;
|
---|
44 | using ILNumerics.Storage;
|
---|
45 |
|
---|
46 | namespace 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<T> 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<int></code>),
|
---|
615 | /// one may use <code>cell.IsTypeOf<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<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<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 | /// <String> first element <Int16> [2,3,4,5,6]
|
---|
633 | /// <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<string>(0));
|
---|
639 | /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf<double>(0));
|
---|
640 | ///
|
---|
641 | /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf<double>(1));
|
---|
642 | /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf<ILCell>(2));
|
---|
643 | ///
|
---|
644 | /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf<short>(0, 1));
|
---|
645 | /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf<ILCell>(1, 1));
|
---|
646 | /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf<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<> 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<double> 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<double> 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<ElementType> 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<double>(1x181)]
|
---|
853 | /// // [innerCell[0], ILArray<double>(1x3)]
|
---|
854 | /// // [ILArray<string>,(1x1)]
|
---|
855 | ///
|
---|
856 | /// cell[0,0] -> will give innerCell eq. ILCell (1x2)
|
---|
857 | /// cell[0,1] -> will give ILArray<string>
|
---|
858 | /// cell[0,0,0,1] -> will give innerCell[1] eq. ILArray<int>(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; // >- will remove the third column (index: 2) from the cell.
|
---|
898 | /// C[full,vec(2,5)] = null; >- will remove columns 3...6
|
---|
899 | /// C[1,1] = null; >- 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 | }
|
---|