[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 System.Text;
|
---|
| 44 | using ILNumerics.Storage;
|
---|
| 45 | using ILNumerics;
|
---|
| 46 | using ILNumerics.Exceptions;
|
---|
| 47 | using ILNumerics.Misc;
|
---|
| 48 |
|
---|
| 49 | namespace ILNumerics {
|
---|
| 50 | /// <summary>
|
---|
| 51 | /// N-dimensional, generic array class, temporary variant, is disposed after first use
|
---|
| 52 | /// </summary>
|
---|
| 53 | /// <typeparam name="ElementType">Inner element type</typeparam>
|
---|
| 54 | public sealed class ILRetArray<ElementType> : ILDenseArray<ElementType> {
|
---|
| 55 |
|
---|
| 56 | #region properties
|
---|
| 57 | /// <summary>
|
---|
| 58 | /// Clone of this array (fast, cheap and shallow)
|
---|
| 59 | /// </summary>
|
---|
| 60 | /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
|
---|
| 61 | /// </remarks>
|
---|
| 62 | public override ILRetArray<ElementType> C {
|
---|
| 63 | get {
|
---|
| 64 | return this;
|
---|
| 65 | }
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | /// <summary>
|
---|
| 69 | /// Size descriptor shortcut
|
---|
| 70 | /// </summary>
|
---|
| 71 | public override ILSize S {
|
---|
| 72 | get {
|
---|
| 73 | using (ILScope.Enter(this))
|
---|
| 74 | return Storage.Size;
|
---|
| 75 | }
|
---|
| 76 | }
|
---|
| 77 | /// <summary>
|
---|
| 78 | /// Size descriptor
|
---|
| 79 | /// </summary>
|
---|
| 80 | public override ILSize Size {
|
---|
| 81 | get {
|
---|
| 82 | using (ILScope.Enter(this))
|
---|
| 83 | return Storage.Size;
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 | /// <summary>
|
---|
| 87 | /// Test if this array instance is a column vector
|
---|
| 88 | /// </summary>
|
---|
| 89 | public override bool IsColumnVector {
|
---|
| 90 | get {
|
---|
| 91 | using (ILScope.Enter(this))
|
---|
| 92 | return Size[1] == 1 && Size.NumberOfDimensions == 2; ;
|
---|
| 93 | }
|
---|
| 94 | }
|
---|
| 95 | /// <summary>
|
---|
| 96 | /// Test if this array instance is a row vector
|
---|
| 97 | /// </summary>
|
---|
| 98 | public override bool IsRowVector {
|
---|
| 99 | get {
|
---|
| 100 | using (ILScope.Enter(this))
|
---|
| 101 | return Size[0] == 1 && Size.NumberOfDimensions == 2;
|
---|
| 102 | }
|
---|
| 103 | }
|
---|
| 104 | /// <summary>
|
---|
| 105 | /// Determine if this array has complex elements.
|
---|
| 106 | /// </summary>
|
---|
| 107 | /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
|
---|
| 108 | public override bool IsComplex {
|
---|
| 109 | get {
|
---|
| 110 | using (ILScope.Enter(this))
|
---|
| 111 | return base.IsComplex;
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
| 114 | /// <summary>
|
---|
| 115 | /// Test if this instance is an empty array (number of elements stored = 0)
|
---|
| 116 | /// </summary>
|
---|
| 117 | public override bool IsEmpty {
|
---|
| 118 | get {
|
---|
| 119 | using (ILScope.Enter(this))
|
---|
| 120 | return Size.NumberOfElements == 0;
|
---|
| 121 | }
|
---|
| 122 | }
|
---|
| 123 | /// <summary>
|
---|
| 124 | /// Test if this instance is a matrix
|
---|
| 125 | /// </summary>
|
---|
| 126 | /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b>
|
---|
| 127 | /// dimensions must equal 2. This attribute is readonly.</remarks>
|
---|
| 128 | public override bool IsMatrix {
|
---|
| 129 | get {
|
---|
| 130 | using (ILScope.Enter(this))
|
---|
| 131 | return Size.NumberOfDimensions == 2;
|
---|
| 132 | }
|
---|
| 133 | }
|
---|
| 134 | /// <summary>
|
---|
| 135 | /// Determine if this array holds numeric values.
|
---|
| 136 | /// </summary>
|
---|
| 137 | /// <remarks>An ILArray is numeric as long as its elements are one of the
|
---|
| 138 | /// following types:
|
---|
| 139 | /// <list type="table">
|
---|
| 140 | /// <listheader>
|
---|
| 141 | /// <term>inner type</term>
|
---|
| 142 | /// </listheader>
|
---|
| 143 | /// <item>
|
---|
| 144 | /// <term>System.double</term>
|
---|
| 145 | /// <description>floating point, real, 8 bytes </description>
|
---|
| 146 | /// </item>
|
---|
| 147 | /// <item>
|
---|
| 148 | /// <term>System.float</term>
|
---|
| 149 | /// <description>floating point real, 4 bytes</description>
|
---|
| 150 | /// </item>
|
---|
| 151 | /// <item>
|
---|
| 152 | /// <term>ILNumerics.complex</term>
|
---|
| 153 | /// <description>floating point complex, 16 bytes</description>
|
---|
| 154 | /// </item>
|
---|
| 155 | /// <item>
|
---|
| 156 | /// <term>ILNumerics.fcomplex</term>
|
---|
| 157 | /// <description>floating point complex, 8 bytes</description>
|
---|
| 158 | /// </item>
|
---|
| 159 | /// <item>
|
---|
| 160 | /// <term>System.char</term>
|
---|
| 161 | /// <description>integer, real, 1 byte</description>
|
---|
| 162 | /// </item>
|
---|
| 163 | /// <item>
|
---|
| 164 | /// <term>System.byte</term>
|
---|
| 165 | /// <description>integer, real, 1 byte</description>
|
---|
| 166 | /// </item>
|
---|
| 167 | /// <item>
|
---|
| 168 | /// <term>System.Int16</term>
|
---|
| 169 | /// <description>integer, real, 2 byte</description>
|
---|
| 170 | /// </item>
|
---|
| 171 | /// <item>
|
---|
| 172 | /// <term>System.Int32</term>
|
---|
| 173 | /// <description>integer, real, 4 byte</description>
|
---|
| 174 | /// </item>
|
---|
| 175 | /// <item>
|
---|
| 176 | /// <term>System.Int64</term>
|
---|
| 177 | /// <description>integer, real, 8 byte</description>
|
---|
| 178 | /// </item>
|
---|
| 179 | /// <item>
|
---|
| 180 | /// <term>System.UInt16</term>
|
---|
| 181 | /// <description>unsigned integer, real, 2 byte</description>
|
---|
| 182 | /// </item>
|
---|
| 183 | /// <item>
|
---|
| 184 | /// <term>System.UInt32</term>
|
---|
| 185 | /// <description>unsigned integer, real, 4 byte</description>
|
---|
| 186 | /// </item>
|
---|
| 187 | /// <item>
|
---|
| 188 | /// <term>System.UInt64</term>
|
---|
| 189 | /// <description>unsigned integer, real, 8 byte</description>
|
---|
| 190 | /// </item>
|
---|
| 191 | /// </list>
|
---|
| 192 | /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
|
---|
| 193 | /// </remarks>
|
---|
| 194 | public override bool IsNumeric {
|
---|
| 195 | get {
|
---|
| 196 | using (ILScope.Enter(this))
|
---|
| 197 | return base.IsNumeric;
|
---|
| 198 | }
|
---|
| 199 | }
|
---|
| 200 | /// <summary>
|
---|
| 201 | /// Test if this instance is a scalar
|
---|
| 202 | /// </summary>
|
---|
| 203 | /// <remarks>This attribute is readonly. It returns: Size.NumberOfElements == 1.</remarks>
|
---|
| 204 | public override bool IsScalar {
|
---|
| 205 | get {
|
---|
| 206 | using (ILScope.Enter(this))
|
---|
| 207 | return Size.NumberOfElements == 1;
|
---|
| 208 | }
|
---|
| 209 | }
|
---|
| 210 | /// <summary>
|
---|
| 211 | /// Test if this array is a vector
|
---|
| 212 | /// </summary>
|
---|
| 213 | /// <remarks>In order for an array to be a vector the number of <b>non singleton</b>
|
---|
| 214 | /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore
|
---|
| 215 | /// it is not sufficient to test for the number of dimensions, but to take the number of
|
---|
| 216 | /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
|
---|
| 217 | public override bool IsVector {
|
---|
| 218 | get {
|
---|
| 219 | using (ILScope.Enter(this))
|
---|
| 220 | return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 | /// <summary>
|
---|
| 224 | /// Length of the longest dimension of this instance
|
---|
| 225 | /// </summary>
|
---|
| 226 | /// <remarks>This property is readonly.
|
---|
| 227 | /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
|
---|
| 228 | public override int Length {
|
---|
| 229 | get {
|
---|
| 230 | using (ILScope.Enter(this))
|
---|
| 231 | return base.Length;
|
---|
| 232 | }
|
---|
| 233 | }
|
---|
| 234 | /// <summary>
|
---|
| 235 | /// Return transposed version of this array
|
---|
| 236 | /// </summary>
|
---|
| 237 | public new ILRetArray<ElementType> T {
|
---|
| 238 | get {
|
---|
| 239 | using (ILScope.Enter(this))
|
---|
| 240 | return new ILRetArray<ElementType>(Storage.ShiftDimensions(1));
|
---|
| 241 | }
|
---|
| 242 | }
|
---|
| 243 | /// <summary>
|
---|
| 244 | /// Gets the name of this array (readonly)
|
---|
| 245 | /// </summary>
|
---|
| 246 | public new String Name {
|
---|
| 247 | get {
|
---|
| 248 | using (ILScope.Enter(this))
|
---|
| 249 | return m_name;
|
---|
| 250 | }
|
---|
| 251 | }
|
---|
| 252 | #endregion
|
---|
| 253 |
|
---|
| 254 | #region constructors
|
---|
| 255 | internal ILRetArray(ILDenseStorage<ElementType> denseStorage) :
|
---|
| 256 | base(denseStorage, true) { }
|
---|
| 257 |
|
---|
| 258 | internal ILRetArray(ElementType[] elements, params int[] dimensions) :
|
---|
| 259 | this(elements, new ILSize(dimensions)) { }
|
---|
| 260 |
|
---|
| 261 | internal ILRetArray(ElementType[] elements, ILSize dimensions) :
|
---|
| 262 | base(new ILDenseStorage<ElementType>(elements, dimensions), true) { }
|
---|
| 263 |
|
---|
| 264 | internal ILRetArray(ILSize dimensions) :
|
---|
| 265 | base(new ILDenseStorage<ElementType>(dimensions), true) { }
|
---|
| 266 |
|
---|
| 267 | internal static ILRetArray<ElementType> empty(ILSize dimension) {
|
---|
| 268 | return new ILRetArray<ElementType>(new ElementType[0], dimension);
|
---|
| 269 | }
|
---|
| 270 |
|
---|
| 271 | #endregion
|
---|
| 272 |
|
---|
| 273 | #region operator overloads
|
---|
| 274 | #region constructive operators
|
---|
| 275 | /// <summary>
|
---|
| 276 | /// Implicitly convert scalar to array of size 1x1 (scalar).
|
---|
| 277 | /// </summary>
|
---|
| 278 | /// <param name="val">Single element of ElementType type</param>
|
---|
| 279 | /// <returns>New array of of size 1x1 holding the only element with value of val.
|
---|
| 280 | /// </returns>
|
---|
| 281 | public static implicit operator ILRetArray<ElementType>(ElementType val) {
|
---|
| 282 | ILRetArray<ElementType> ret = new ILRetArray<ElementType>(
|
---|
| 283 | new ILDenseStorage<ElementType>(new ElementType[] { val }, new ILSize(1, 1)));
|
---|
| 284 | return ret;
|
---|
| 285 | }
|
---|
| 286 | /// <summary>
|
---|
| 287 | /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
|
---|
| 288 | /// </summary>
|
---|
| 289 | /// <param name="A">1-dimensional system array, arbitrary type</param>
|
---|
| 290 | /// <returns>ILNumerics array of same element type as elements of A.
|
---|
| 291 | /// Row vector. If A is null: empty array.</returns>
|
---|
| 292 | /// <remarks>The System.Array A will directly be used for the new ILNumerics array!
|
---|
| 293 | /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
|
---|
| 294 | public static implicit operator ILRetArray<ElementType>(ElementType[] A) {
|
---|
| 295 | if (A == null) {
|
---|
| 296 | // TODO: check: return null better?
|
---|
| 297 | ILDenseStorage<ElementType> dS = new ILDenseStorage<ElementType>(new ElementType[0], ILSize.Empty00);
|
---|
| 298 | return new ILRetArray<ElementType>(dS);
|
---|
| 299 | }
|
---|
| 300 | return new ILRetArray<ElementType>(A, 1, A.Length);
|
---|
| 301 | }
|
---|
| 302 | /// <summary>
|
---|
| 303 | /// Implicitly convert n-dim. System.Array to ILNumerics array
|
---|
| 304 | /// </summary>
|
---|
| 305 | /// <param name="A">Arbitrarily sized System.Array</param>
|
---|
| 306 | /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
|
---|
| 307 | /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
|
---|
| 308 | /// <typeparamref name="ElementType"/>. The resulting ILArray will reflect all dimensions of
|
---|
| 309 | /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
|
---|
| 310 | /// <exception cref="ILNumerics.Exceptions.ILCastException">If type of input does not match
|
---|
| 311 | /// ElementType</exception>
|
---|
| 312 | public static implicit operator ILRetArray<ElementType>(Array A) {
|
---|
| 313 | if (A == null || A.Length == 0) {
|
---|
| 314 | // TODO: check: return null better?
|
---|
| 315 | return new ILRetArray<ElementType>(ILSize.Empty00);
|
---|
| 316 | }
|
---|
| 317 | if (A.GetType().GetElementType() != typeof(ElementType))
|
---|
| 318 | throw new ILCastException("inner type of System.Array must match");
|
---|
| 319 | int[] dims = new int[A.Rank];
|
---|
| 320 | ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
|
---|
| 321 | int posArr = 0;
|
---|
| 322 | for (int i = 0; i < dims.Length; i++) {
|
---|
| 323 | dims[i] = A.GetLength(dims.Length - i - 1);
|
---|
| 324 | }
|
---|
| 325 | foreach (ElementType item in A)
|
---|
| 326 | retArr[posArr++] = item;
|
---|
| 327 | return new ILRetArray<ElementType>(retArr, dims);
|
---|
| 328 | }
|
---|
| 329 | /// <summary>
|
---|
| 330 | /// Implicitly cast two dimensional System.Array to ILNumerics array
|
---|
| 331 | /// </summary>
|
---|
| 332 | /// <param name="A">2-dimensional System.Array</param>
|
---|
| 333 | /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
|
---|
| 334 | public static implicit operator ILRetArray<ElementType>(ElementType[,] A) {
|
---|
| 335 | if (A == null || A.Length == 0) {
|
---|
| 336 | // TODO: check: return null better?
|
---|
| 337 | return new ILRetArray<ElementType>(ILSize.Empty00);
|
---|
| 338 | }
|
---|
| 339 | int[] dims = new int[2];
|
---|
| 340 | ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
|
---|
| 341 | int posArr = 0;
|
---|
| 342 | for (int i = 0; i < 2; i++) {
|
---|
| 343 | dims[i] = A.GetLength(dims.Length - i - 1);
|
---|
| 344 | }
|
---|
| 345 | foreach (ElementType item in A)
|
---|
| 346 | retArr[posArr++] = item;
|
---|
| 347 | return new ILRetArray<ElementType>(retArr, dims);
|
---|
| 348 | }
|
---|
| 349 | /// <summary>
|
---|
| 350 | /// Implicitly cast three dimensional System.Array to ILNumerics array
|
---|
| 351 | /// </summary>
|
---|
| 352 | /// <param name="A">3-dimensional System.Array</param>
|
---|
| 353 | /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
|
---|
| 354 | public static implicit operator ILRetArray<ElementType>(ElementType[, ,] A) {
|
---|
| 355 | if (A == null || A.Length == 0) {
|
---|
| 356 | // TODO: check: return null better?
|
---|
| 357 | return new ILRetArray<ElementType>(ILSize.Empty00);
|
---|
| 358 | }
|
---|
| 359 | int[] dims = new int[3];
|
---|
| 360 | ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
|
---|
| 361 | int posArr = 0;
|
---|
| 362 | for (int i = 0; i < 3; i++) {
|
---|
| 363 | dims[i] = A.GetLength(dims.Length - i - 1);
|
---|
| 364 | }
|
---|
| 365 | foreach (ElementType item in A)
|
---|
| 366 | retArr[posArr++] = item;
|
---|
| 367 | return new ILRetArray<ElementType>(retArr, dims);
|
---|
| 368 | }
|
---|
| 369 | /// <summary>
|
---|
| 370 | /// Convert array to temporary cell
|
---|
| 371 | /// </summary>
|
---|
| 372 | /// <param name="A">Source array</param>
|
---|
| 373 | /// <returns>Temporary scalar cell, having the only element with a clone of A</returns>
|
---|
| 374 | public static implicit operator ILRetCell(ILRetArray<ElementType> A) {
|
---|
| 375 | using (ILScope.Enter(A)) {
|
---|
| 376 | ILRetCell ret = new ILRetCell(ILSize.Scalar1_1, A.Storage);
|
---|
| 377 | ret.Storage.FromImplicitCast = true;
|
---|
| 378 | return ret;
|
---|
| 379 | }
|
---|
| 380 | }
|
---|
| 381 | #endregion
|
---|
| 382 |
|
---|
| 383 | #region implicit conversions
|
---|
| 384 | /// <summary>
|
---|
| 385 | /// 'Clone' conversion
|
---|
| 386 | /// </summary>
|
---|
| 387 | /// <param name="A">Source array</param>
|
---|
| 388 | /// <returns>Temporary ILArray, will be disposed after next operation</returns>
|
---|
| 389 | /// <remarks>This conversion is for convenient reasons only. It enables the direct
|
---|
| 390 | /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray
|
---|
| 391 | /// is required. A (fast) clone will be made. This is an alias for A.C.</remarks>
|
---|
| 392 | public static implicit operator ILRetArray<ElementType>(ILArray<ElementType> A) {
|
---|
| 393 | if (object.Equals(A,null)) return null;
|
---|
| 394 | return A.C;
|
---|
| 395 | }
|
---|
| 396 | /// <summary>
|
---|
| 397 | /// 'Clone' conversion
|
---|
| 398 | /// </summary>
|
---|
| 399 | /// <param name="A">Source array</param>
|
---|
| 400 | /// <returns>Temporary ILArray, will be disposed after next operation</returns>
|
---|
| 401 | /// <remarks>This conversion is for convenient reasons only. It enables the direct
|
---|
| 402 | /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray
|
---|
| 403 | /// is required. One example is the conversion of ILArray as return type.
|
---|
| 404 | /// A (fast) clone will be made. This is an alias for A.C.</remarks>
|
---|
| 405 | public static implicit operator ILRetArray<ElementType>(ILInArray<ElementType> A) {
|
---|
| 406 | if (object.Equals(A, null)) return null;
|
---|
| 407 | return A.C;
|
---|
| 408 | }
|
---|
| 409 | /// <summary>
|
---|
| 410 | /// 'Clone' conversion
|
---|
| 411 | /// </summary>
|
---|
| 412 | /// <param name="A">Source array</param>
|
---|
| 413 | /// <returns>temporary ILArray, will be disposed after next operation</returns>
|
---|
| 414 | /// <remarks>This conversion is for convenient reasons only. It enables the direct
|
---|
| 415 | /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray
|
---|
| 416 | /// is required. One example is the conversion of ILArray as return type.
|
---|
| 417 | /// A (fast) clone will be made. This is an alias for A.C.</remarks>
|
---|
| 418 | public static implicit operator ILRetArray<ElementType>(ILOutArray<ElementType> A) {
|
---|
| 419 | if (object.Equals(A, null)) return null;
|
---|
| 420 | return A.C;
|
---|
| 421 | }
|
---|
| 422 | #endregion
|
---|
| 423 | #endregion operator overloads
|
---|
| 424 |
|
---|
| 425 | #region public function
|
---|
| 426 | /// <summary>
|
---|
| 427 | /// Clone of this array
|
---|
| 428 | /// </summary>
|
---|
| 429 | /// <remarks><para>
|
---|
| 430 | /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means,
|
---|
| 431 | /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same
|
---|
| 432 | /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays
|
---|
| 433 | /// on write access.</para>
|
---|
| 434 | /// <para>The clone returned will be of the same type as this instance.</para></remarks>
|
---|
| 435 | internal override ILBaseArray Clone() {
|
---|
| 436 | return this;
|
---|
| 437 | }
|
---|
| 438 | /// <summary>
|
---|
| 439 | /// Concatenate this array
|
---|
| 440 | /// </summary>
|
---|
| 441 | /// <param name="A">n-dimensional storage</param>
|
---|
| 442 | /// <param name="dim">Dimension index along which to concatenate the arrays.</param>
|
---|
| 443 | /// <returns>New array with copy elements of this array and A</returns>
|
---|
| 444 | /// <remarks>The array returned will be a copy of both arrays involved. None
|
---|
| 445 | /// of the input arrays will be altered. If <paramref name="dim"/> is larger than
|
---|
| 446 | /// the number of dimensions of one of the arrays its value will be used in modulus.
|
---|
| 447 | /// <para>The resulting array has the size of both input arrays, laid beside one
|
---|
| 448 | /// another along the <paramref name="dim"/> dimension.</para></remarks>
|
---|
| 449 | public new ILRetArray<ElementType> Concat(ILInArray<ElementType> A, int dim) {
|
---|
| 450 | using (ILScope.Enter(this,A))
|
---|
| 451 | return new ILRetArray<ElementType>(Storage.Concat(A.Storage, dim));
|
---|
| 452 | }
|
---|
| 453 | /// <summary>
|
---|
| 454 | /// Compare elements and shape of this array with another array
|
---|
| 455 | /// </summary>
|
---|
| 456 | /// <param name="A">Other array</param>
|
---|
| 457 | /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
|
---|
| 458 | /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays.</para></remarks>
|
---|
| 459 | public override bool Equals(object A) {
|
---|
| 460 | using (ILScope.Enter(this))
|
---|
| 461 | return base.Equals(A);
|
---|
| 462 | }
|
---|
| 463 | /// <summary>
|
---|
| 464 | /// Copy values of all elements into System.Array.
|
---|
| 465 | /// </summary>
|
---|
| 466 | /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
|
---|
| 467 | /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and
|
---|
| 468 | /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements,
|
---|
| 469 | /// it will be recreated from the ILNumerics memory pool.</remarks>
|
---|
| 470 | public new void ExportValues(ref ElementType[] outArray) {
|
---|
| 471 | using (ILScope.Enter(this))
|
---|
| 472 | Storage.ExportValues(ref outArray);
|
---|
| 473 | }
|
---|
| 474 | /// <summary>
|
---|
| 475 | /// Enumerator returning elements as ElementType
|
---|
| 476 | /// </summary>
|
---|
| 477 | /// <returns>Enumerator</returns>
|
---|
| 478 | /// <remarks>This method enables the use of ILNumerics arrays in foreach loops.
|
---|
| 479 | /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator
|
---|
| 480 | /// is compatible with ILNumerics memory management.</para></remarks>
|
---|
| 481 | /// <example><code>ILArray<double> A = rand(5,4,6);
|
---|
| 482 | /// foreach (double element in A) {
|
---|
| 483 | /// // all elements are scalar double values
|
---|
| 484 | /// String.Format("Element: {0} ", element);
|
---|
| 485 | /// // Note: 'element' cannot be used to alter the collection!
|
---|
| 486 | /// } </code>
|
---|
| 487 | /// </example>
|
---|
| 488 | public override IEnumerator<ElementType> GetEnumerator() {
|
---|
| 489 | using (ILScope.Enter(this)) {
|
---|
| 490 | ElementType[] values = GetArrayForRead();
|
---|
| 491 | int len = Size.NumberOfElements;
|
---|
| 492 | for (int i = 0; i < len; i++)
|
---|
| 493 | yield return values[i];
|
---|
| 494 | }
|
---|
| 495 | }
|
---|
| 496 | /// <summary>
|
---|
| 497 | /// Generate a hash code based on the current arrays values
|
---|
| 498 | /// </summary>
|
---|
| 499 | /// <returns>Hash code</returns>
|
---|
| 500 | /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
|
---|
| 501 | /// Therefore, the function must iterate over all elements in the array - which makes it somehow a costly
|
---|
| 502 | /// operation. Take this into account, if you consider using large arrays in collections like dictionaries
|
---|
| 503 | /// or hashtables, which make great use of hash codes.
|
---|
| 504 | /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
|
---|
| 505 | public override int GetHashCode() {
|
---|
| 506 | using (ILScope.Enter(this))
|
---|
| 507 | return base.GetHashCode();
|
---|
| 508 | }
|
---|
| 509 | /// <summary>
|
---|
| 510 | /// Get minimum and maximum value of all elements - if any
|
---|
| 511 | /// </summary>
|
---|
| 512 | /// <param name="min">[Output] Minimum value</param>
|
---|
| 513 | /// <param name="max">[Output] Maximum value</param>
|
---|
| 514 | /// <returns>true if the limits exists and could be computed, false otherwise</returns>
|
---|
| 515 | /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
|
---|
| 516 | /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
|
---|
| 517 | public override bool GetLimits(out ElementType min, out ElementType max) {
|
---|
| 518 | using (ILScope.Enter(this))
|
---|
| 519 | return base.GetLimits(out min, out max);
|
---|
| 520 | }
|
---|
| 521 | /// <summary>
|
---|
| 522 | /// Get single element from this array
|
---|
| 523 | /// </summary>
|
---|
| 524 | /// <param name="idx">Indices, location of element</param>
|
---|
| 525 | /// <returns>The requested element</returns>
|
---|
| 526 | public override ElementType GetValue(params int[] idx) {
|
---|
| 527 | using (ILScope.Enter(this))
|
---|
| 528 | return base.GetValue(idx);
|
---|
| 529 | }
|
---|
| 530 | /// <summary>
|
---|
| 531 | /// Create replication of this array
|
---|
| 532 | /// </summary>
|
---|
| 533 | /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is
|
---|
| 534 | /// less than the number of dimensions in this array, the trailing dimensions will
|
---|
| 535 | /// be set to 1 (singleton dimensions). On the other hand, if the number specified
|
---|
| 536 | /// is larger then the number of dimension stored inside the storge the resulting
|
---|
| 537 | /// storage will get its number of dimensions extended accordingly. </param>
|
---|
| 538 | /// <returns>Array being created by multiple replications of this array along
|
---|
| 539 | /// arbitrary dimensions according to <paramref name="dims"/></returns>
|
---|
| 540 | public new ILRetArray<ElementType> Repmat(params int[] dims) {
|
---|
| 541 | using (ILScope.Enter(this))
|
---|
| 542 | return new ILRetArray<ElementType>(Storage.Repmat(dims));
|
---|
| 543 | }
|
---|
| 544 | /// <summary>
|
---|
| 545 | /// Reshaped copy of this array
|
---|
| 546 | /// </summary>
|
---|
| 547 | /// <param name="dimensions">New dimensions of the array</param>
|
---|
| 548 | /// <returns>Reshaped copy of the array</returns>
|
---|
| 549 | /// <remarks><para>The current instance will not be changed. A new storage is created, having
|
---|
| 550 | /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
|
---|
| 551 | /// </remarks>
|
---|
| 552 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in <paramref name="dimensions"/>
|
---|
| 553 | /// do not match the number of elements in this array.</exception>
|
---|
| 554 | public new ILRetArray<ElementType> Reshape(ILSize dimensions) {
|
---|
| 555 | using (ILScope.Enter(this)) {
|
---|
| 556 | ILArray<ElementType> ret = C;
|
---|
| 557 | ret.Storage.Reshape(dimensions);
|
---|
| 558 | return ret;
|
---|
| 559 | }
|
---|
| 560 | }
|
---|
| 561 | /// <summary>
|
---|
| 562 | /// Serialize this ILArray into a binary stream.
|
---|
| 563 | /// </summary>
|
---|
| 564 | /// <param name="outStream">System.IO.Stream to receive the byte stream
|
---|
| 565 | /// for this ILBaseArray</param>
|
---|
| 566 | /// <returns>True on success, false on error.</returns>
|
---|
| 567 | /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
|
---|
| 568 | /// </remarks>
|
---|
| 569 | public override bool Serialize(Stream outStream) {
|
---|
| 570 | using (ILScope.Enter(this))
|
---|
| 571 | return base.Serialize(outStream);
|
---|
| 572 | }
|
---|
| 573 | /// <summary>
|
---|
| 574 | /// Create array from this array and shift dimensions
|
---|
| 575 | /// </summary>
|
---|
| 576 | /// <param name="shift">Number of dimensions to shift</param>
|
---|
| 577 | /// <returns>Shifted version of this array</returns>
|
---|
| 578 | /// <remarks><para>The shift is done 'to the left':</para>
|
---|
| 579 | /// <example><code>ILArray<double> A = zeros(2,4);
|
---|
| 580 | /// ILArray<double> B = A.Shifted(1);
|
---|
| 581 | /// // B is now: <double> [4,2]
|
---|
| 582 | ///
|
---|
| 583 | /// ILArray<double> C = zeros(2,4,3);
|
---|
| 584 | /// ILArray<double> D = C.Shifted(1);
|
---|
| 585 | /// // D is now: <double> [4,3,2]
|
---|
| 586 | /// </code></example>
|
---|
| 587 | /// <para>The dimensions are shifted circulary to the left. This
|
---|
| 588 | /// can be imagined as removing the first dimensions from the beginning of the list of
|
---|
| 589 | /// dimensions and "append" them to the end in a ringbuffer style.</para>
|
---|
| 590 | /// <para>For dimension shifts of '1', you may consider using the
|
---|
| 591 | /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
|
---|
| 592 | /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
|
---|
| 593 | /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
|
---|
| 594 | public new ILRetArray<ElementType> Shifted(int shift) {
|
---|
| 595 | using (ILScope.Enter(this))
|
---|
| 596 | return new ILRetArray<ElementType>(Storage.ShiftDimensions(shift));
|
---|
| 597 | }
|
---|
| 598 | /// <summary>
|
---|
| 599 | /// Subarray creation
|
---|
| 600 | /// </summary>
|
---|
| 601 | /// <param name="size">Range specification, defining the size of the subarray</param>
|
---|
| 602 | /// <returns>Subarray as copy of a part of this array</returns>
|
---|
| 603 | /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
|
---|
| 604 | public new ILRetArray<ElementType> Subarray(params ILBaseArray[] size) {
|
---|
| 605 | using (ILScope.Enter(this))
|
---|
| 606 | using (ILScope.Enter(size))
|
---|
| 607 | return new ILRetArray<ElementType>(Storage.Subarray(size));
|
---|
| 608 | }
|
---|
| 609 |
|
---|
| 610 | ///// <summary>
|
---|
| 611 | ///// Short textual summary of this instance; used for debug output
|
---|
| 612 | ///// </summary>
|
---|
| 613 | ///// <returns>String representation of type and size</returns>
|
---|
| 614 | ///// <remarks>The type of elements and the size of the array are displayed. If the array
|
---|
| 615 | ///// is scalar, its value is displayed next to the type.
|
---|
| 616 | ///// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
|
---|
| 617 | //public override string ShortInfo() {
|
---|
| 618 | // using (ILScope.Enter(this))
|
---|
| 619 | // return base.ShortInfo();
|
---|
| 620 | //}
|
---|
| 621 |
|
---|
| 622 | /// <summary>
|
---|
| 623 | /// Send values of this instance to stream.
|
---|
| 624 | /// </summary>
|
---|
| 625 | /// <param name="stream">Stream to write the values into.</param>
|
---|
| 626 | /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
|
---|
| 627 | /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
|
---|
| 628 | /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
|
---|
| 629 | /// the values will be serialized.</param>
|
---|
| 630 | /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s)
|
---|
| 631 | /// will be replaced from the format string before applying to the elements. This is done to
|
---|
| 632 | /// prevent the format from breaking the 'page' style of the output.</para>
|
---|
| 633 | /// <para>If 'method' is set to 'Matlab', the array will be written as Matfile version 5.0. No compression will be used. The internal 'Name' property will be used as the
|
---|
| 634 | /// array name for writing. This array instance will be the only array in the .mat file. If you want to write several arrays bundled into one mat file, use the MatFile class to
|
---|
| 635 | /// create a collection of arrays and write the MatFile to stream.</para></remarks>
|
---|
| 636 | public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
|
---|
| 637 | using (ILScope.Enter(this))
|
---|
| 638 | try {
|
---|
| 639 | int len;
|
---|
| 640 | switch (method) {
|
---|
| 641 | case ILArrayStreamSerializationFlags.Serial:
|
---|
| 642 | len = Size.NumberOfElements;
|
---|
| 643 | using (TextWriter tw = new StreamWriter(stream)) {
|
---|
| 644 | for (int i = 0; i < len; i++) {
|
---|
| 645 | tw.Write(format, GetValue(i));
|
---|
| 646 | }
|
---|
| 647 | }
|
---|
| 648 | break;
|
---|
| 649 | case ILArrayStreamSerializationFlags.Formatted:
|
---|
| 650 | format = format.Replace(Environment.NewLine, "");
|
---|
| 651 | ILDenseStorage<ElementType> temp = this.Storage.ShiftDimensions(1);
|
---|
| 652 | //len = Dimensions.NumberOfElements / Dimensions[1];
|
---|
| 653 | using (TextWriter tw = new StreamWriter(stream)) {
|
---|
| 654 | tw.Write(temp.ValuesToString(0));
|
---|
| 655 | }
|
---|
| 656 | break;
|
---|
| 657 | case ILArrayStreamSerializationFlags.Matlab:
|
---|
| 658 | ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
|
---|
| 659 | mf.Write(stream);
|
---|
| 660 | break;
|
---|
| 661 | }
|
---|
| 662 | } catch (Exception e) {
|
---|
| 663 | throw new ILException("ToStream: Could not serialize to stream.", e);
|
---|
| 664 | }
|
---|
| 665 | }
|
---|
| 666 | #endregion
|
---|
| 667 |
|
---|
| 668 | #region indexer
|
---|
| 669 | /// <summary>
|
---|
| 670 | /// Subarray creation
|
---|
| 671 | /// </summary>
|
---|
| 672 | /// <param name="range">Range specification, defining the size of the subarray</param>
|
---|
| 673 | /// <returns>Subarray as copy of a part of this array</returns>
|
---|
| 674 | /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
|
---|
| 675 | public ILRetArray<ElementType> this[params ILBaseArray[] range] {
|
---|
| 676 | get {
|
---|
| 677 | using (ILScope.Enter(this))
|
---|
| 678 | using (ILScope.Enter(range))
|
---|
| 679 | return new ILRetArray<ElementType>(Storage.Subarray(range));
|
---|
| 680 | }
|
---|
| 681 | }
|
---|
| 682 | #endregion
|
---|
| 683 |
|
---|
| 684 | #region memory management
|
---|
| 685 | internal override bool EnterScope() {
|
---|
| 686 | return false;
|
---|
| 687 | }
|
---|
| 688 | #endregion
|
---|
| 689 | }
|
---|
| 690 | }
|
---|