[9102] | 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 | }
|
---|