/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// Permission is hereby granted, free of charge, to any person obtaining a copy /// of this software and associated documentation files (the "Software"), to deal /// in the Software without restriction, including without limitation the rights to /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of /// the Software, and to permit persons to whom the Software is furnished to do /// so, subject to the following conditions: /// /// The above copyright notice and this permission notice shall be included in all /// copies or substantial portions of the Software. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILNumerics.Storage; using ILNumerics.Exceptions; namespace ILNumerics { /// /// Rectangular array, used as output parameter only /// /// Inner type. This will mostly be a system numeric type or a /// complex floating point type. /// This class extends the primary ILArray by optimizing its behavior for the case when used as an /// output parameter of functions.When writing your own function all output parameters should be of type ILOutArray. Do not /// use out ILArray! Similary, all return types should be of type and all input parameters of type . /// Other than being used to retrieve results from functions, ILOutArray should not be used. /// /// /// /// [Serializable] public sealed class ILOutArray : ILDenseArray { #region attributes private ILArray m_originalArray; private static bool s_isTempArray = false; #endregion #region constructors /// /// Create new output parameter array /// /// Dense storage for the new array internal ILOutArray(ILDenseStorage storage) : base(storage, s_isTempArray) { //ILScope.Context.RegisterArray(this); } #endregion #region implicit cast operators #region constructional operators ///// ///// Implicitly convert scalar to array of size 1x1 (scalar). ///// ///// System type of size scalar ///// New ILOutArray of type ILOutArray ]]> of size 1x1 ///// holding the only element with value of val. ///// //public static implicit operator ILOutArray (ElementType val) { // ILOutArray ret = new ILOutArray( // new ILDenseStorage( // new ElementType[1] {val}, // new ILSize(1,1))); // return ret; //} ///// ///// implicitly cast one dimensional System.Array to ILNumerics array (vector) ///// ///// 1 dimensional system array, arbitrary type ///// ILNumerics array of same element type as elements of A. ///// Row vector. If A is null: empty array. ///// The System.Array A will directly be used for the new ILNumerics array! ///// No copy will be done! Make sure, not to reference A after this conversion! //public static implicit operator ILOutArray (ElementType[] A) { // if (A == null) { // ILDenseStorage dS = new ILDenseStorage(new ElementType[0], ILSize.Empty00); // return new ILOutArray(dS); // } // return new ILOutArray(A,1,A.Length); // constructor will register the array in scope context! //} ///// ///// implicitly convert n-dimensional System.Array to ILNumerics array ///// ///// arbitrarily sized System.Array ///// If A is null: empty array. Else: new ILNumerics array of the same size as A ///// The inner type of input array must match the requested type ///// . The resulting ILOutArray will reflect all dimensions of ///// A. Elements of A will get copied to elements of output array (shallow copy). ///// if type of input does not match ///// ElementType //public static implicit operator ILOutArray (Array elements) { // if (elements == null || elements.Length == 0) { // return new ILOutArray(ILSize.Empty00); // } // if (elements.GetType().GetElementType() != typeof(ElementType)) // throw new ILCastException("inner type of System.Array must match"); // int [] dims = new int[elements.Rank]; // ElementType [] retArr = ILMemoryPool.Pool.New(elements.Length); // int posArr = 0; // for (int i = 0; i < dims.Length; i++) { // dims[i] = elements.GetLength(dims.Length-i-1); // } // foreach (ElementType item in elements) // retArr[posArr++] = item; // ILOutArray ret = new ILOutArray(retArr,dims); // return ret; //} ///// ///// implicitly cast two dimensional System.Array to ILNumerics array ///// ///// 2D System.Array ///// If A is null: empty array. ILNumerics array of same size and type as A otherwise. //public static implicit operator ILOutArray(ElementType[,] A) { // if (A == null || A.Length == 0) { // return new ILOutArray(ILSize.Empty00); // } // int[] dims = new int[2]; // ElementType[] retArr = ILMemoryPool.Pool.New(A.Length); // int posArr = 0; // for (int i = 0; i < 2; i++) { // dims[i] = A.GetLength(dims.Length - i - 1); // } // foreach (ElementType item in A) // retArr[posArr++] = item; // ILOutArray ret = new ILOutArray(retArr, dims); // return ret; //} ///// ///// implicitly cast three dimensional System.Array to ILNumerics array ///// ///// 3D System.Array ///// If A is null: empty array. ILNumerics array of same size and type as A otherwise. //public static implicit operator ILOutArray(ElementType[,,] A) { // if (A == null || A.Length == 0) { // return new ILOutArray(ILSize.Empty00); // } // int[] dims = new int[3]; // ElementType[] retArr = ILMemoryPool.Pool.New(A.Length); // int posArr = 0; // for (int i = 0; i < 3; i++) { // dims[i] = A.GetLength(dims.Length - i - 1); // } // foreach (ElementType item in A) // retArr[posArr++] = item; // ILOutArray ret = new ILOutArray(retArr, dims); // return ret; //} #endregion #region conversional operators /// /// Creates an output parameter type array from regular array /// /// Original array /// Output parameter type array, references the original array public static implicit operator ILOutArray(ILArray A) { if (object.Equals(A, null)) return null; // we over take the storage (identical reference) to the new OutArray // and store the reference to the original as well. // It will be needed to synchronize changes to the denseStorage later (on Remove and Expand). ILOutArray ret = new ILOutArray(A.Storage); ret.m_originalArray = A; return ret; } #endregion #endregion #region memory management /// /// Replace the elements of this array with another array's elements, preventing memory leaks /// /// New array public ILRetArray a { set { Assign(value); } get { return this.C; } } /// /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal /// /// New array public void Assign(ILRetArray value) { if (!IsDisposed) Storage.Dispose(); ILDenseStorage storage = value.GiveStorageAwayOrClone(); m_storage = storage; if (!object.ReferenceEquals(m_originalArray, null)) { // update original array as well (m_originalArray as ILDenseArray).Storage = storage; } //ILScope.Context.RegisterArray(this); } internal override bool EnterScope() { return false; } #endregion #region mutability + indexer /// /// Set single value to element at index specified /// /// New value /// Index of element to be altered public void SetValue(ElementType value, params int[] idx) { Storage.SetValueTyped(value, idx); } /// /// Alter range of this array /// /// Array with new values /// Range specification public void SetRange(ILInArray value, params ILBaseArray[] range) { using (ILScope.Enter(value)) using (ILScope.Enter(range)) { if (object.Equals(value, null)) { Storage.IndexSubrange(null, range); } else { using (ILScope.Enter(value)) Storage.IndexSubrange(value.Storage, range); } } } /// /// Subarray creation/manipulation/deletion /// /// Range specification, defining the size of the subarray /// Subarray as copy of this array public ILRetArray this[params ILBaseArray[] range] { get { using (ILScope.Enter(range)) return new ILRetArray(Storage.Subarray(range)); } set { SetRange(value, range); } } #endregion } }