Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1967: ILNumerics source for experimentation

File size: 21.5 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Collections.Generic;
42using ILNumerics.Storage;
43using System.IO;
44using ILNumerics.Exceptions;
45
46namespace ILNumerics {
47    [System.Diagnostics.DebuggerTypeProxy(typeof(ILNumerics.Misc.ILArrayDebuggerProxy<>))]
48    [System.Diagnostics.DebuggerDisplay("{ShortInfo(),nq}")]
49    [Serializable]
50    // ToDo: DOKU for ILDenseArray<ElementType> missing
51    public partial class ILDenseArray<ElementType> : ILBaseArray<ElementType> {
52
53        #region constructors
54        internal ILDenseArray(ILStorage storage, bool isTempArray)
55            : base(storage, isTempArray) {
56
57        }
58        #endregion
59
60        #region properties
61        /// <summary>
62        /// internal access to the underlying storage
63        /// </summary>
64        internal new ILDenseStorage<ElementType> Storage {
65            get { return (m_storage as ILDenseStorage<ElementType>); }
66            set {
67                // e.g. Storage.Detach() may return itself (if no detaching is
68                // required). So we must check for that equalty here!
69                if (!object.Equals(value, m_storage)) {
70                    m_storage.Dispose();
71                    m_storage = value;
72                }
73            }
74        }
75        /// <summary>
76        /// Clone of this array (fast, lazy and shallow)
77        /// </summary>
78        public virtual ILRetArray<ElementType> C {
79            get {
80                return new ILRetArray<ElementType>((ILDenseStorage<ElementType>)Storage.Clone());
81            }
82        }
83        /// <summary>
84        /// Return transposed version of this array
85        /// </summary>
86        /// <remarks>For matrices, this swaps columns with rows. For arrays, the dimensions are shifted by one.
87        /// <para>Note, for complex elements, <b>no</b> conjugate is created! Use conj(A.T) if this is intended.</para></remarks>
88        public ILRetArray<ElementType> T {
89            get {
90                // if this is updated to create a conjugate for complex data types
91                // -> do not forget to update quick reference ILNumerics4Matlab also!
92                return new ILRetArray<ElementType>(Storage.ShiftDimensions(1));
93            }
94        }
95        /// <summary>
96        ///  [deprecated] Get maximum value of array - if any
97        /// </summary>
98        /// <remarks>This property is marked as deprecated and will be removed in a future version. Use one of the
99        /// following alternatives instead:
100        /// </remarks>
101        /// <seealso cref="ILNumerics.ILBaseArray&lt;ElementType>.GetLimits(out ElementType, out ElementType)"/>
102        [Obsolete()]
103        public ElementType MaxValue {
104            get {
105                ElementType ret, dummy;
106                GetLimits(out dummy, out ret);
107                return ret;
108            }
109        }
110        /// <summary>
111        ///  [deprecated] Get minimum value of array - if any
112        /// </summary>
113        /// <remarks>This property is marked as deprecated and will be removed in a future version. Use one of the
114        /// following alternatives instead:
115        /// <list type="bullets">
116        /// <item><seealso cref="ILNumerics.ILBaseArray{T}.GetLimits"/></item>
117        /// <item><seealso cref="ILNumerics.ILMath.minall"/></item>
118        /// </list></remarks>
119        [Obsolete()]
120        public ElementType MinValue {
121            get {
122                ElementType ret, dummy;
123                GetLimits(out ret, out dummy);
124                return ret;
125            }
126        }
127        #endregion
128
129        #region memory management
130        /// <summary>
131        /// Get number of arrays, referencing the same underlying data storage
132        /// </summary>
133        /// <return>This number is always greater than or equal to 1.</return>
134        /// <remarks>For temporary arrays, calling this property does not - as usual -
135        /// disposes the array</remarks>
136        public int ReferenceCount {
137            get {
138                return Storage.ReferenceCount;
139            }
140        }
141
142        #endregion
143
144        #region public function
145        /// <summary>
146        /// Clone of this array
147        /// </summary>
148        /// <remarks><para>
149        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means,
150        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same
151        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays
152        /// on write access.</para>
153        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
154        internal override ILBaseArray Clone() {
155            ILRetArray<ElementType> ret = new ILRetArray<ElementType>((ILDenseStorage<ElementType>)Storage.Clone());
156            return ret;
157        }
158        /// <summary>
159        /// Concatenate this array
160        /// </summary>
161        /// <param name="A">N-dimensional array. Except for dimensions <paramref name="dim"/>
162        /// the dimensions of A must match the dimensions of this storage</param>
163        /// <param name="dim">Index of dimension to concatenate arrays along.
164        /// If dim is larger than the number of dimensions of any of the arrays,
165        /// its value will be used in modulus the number of dimensions.</param>
166        /// <returns>New array having the size
167        /// of both input arrays layed behind each other along the dim's-dimension</returns>
168        public ILRetArray<ElementType> Concat(ILInArray<ElementType> A, int dim) {
169            using (ILScope.Enter(A))
170                return new ILRetArray<ElementType>(Storage.Concat(A.Storage, dim));
171        }
172        /// <summary>
173        /// Copy values of all elements into System.Array.
174        /// </summary>
175        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
176        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and
177        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements,
178        /// it will be recreated from the ILNumerics memory pool.</remarks>
179        public void ExportValues(ref ElementType[] outArray) {
180            Storage.ExportValues(ref outArray);
181        }
182        /// <summary>
183        /// Get direct reference to inner System.Array storage for <b>read access</b> - use with care!
184        /// </summary>
185        /// <returns>Reference to inner System.Array for reading</returns>
186        /// <remarks>This method is provided for experts only! Altering elements of this
187        /// array may cause the data to be invalidated or corrupted! Use this array only for reading! Note
188        /// the ILNumerics array storage format (column major). Keep in mind, the length
189        /// of the array may exceeds the number of elements!
190        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only!
191        /// Unless you really know, what you are doing, you should rather use the higher order access
192        /// methods provided by ILArray&lt;T>!</para>
193        /// <para>Unlike (almost) all other member function of an array, this function
194        /// does not keep track of internal memory management. It means, the storage which this array is based
195        /// upon, will not be set free after the function returns. You (as the user of the array) will have to pay
196        /// attention yourself, when to call dispose on the array - if necessary. Also, for elements of reference
197        /// types (e.g. ILCell), retrieving and storing elements from/into the System.Array directly does
198        /// not simulate a value semantic as all other functions do! This means, references are copied. Attention
199        /// must be paid to dereference / clone elements accordingly. </para></remarks>
200        public ElementType[] GetArrayForRead() {
201            return Storage.GetArrayForRead();
202        }
203        /// <summary>
204        /// Direct reference to inner System.Array storage for write access - use with care!
205        /// </summary>
206        /// <returns>Reference to inner System.Array</returns>
207        /// <remarks>Altering this array can be done directly. If necessary, the array is detached before
208        /// returned. Watch the column order format of storages in ILNumerics. Keep in mind, the length
209        /// of the System.Array may exceed the number of elements of the ILNumerics array.
210        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only.
211        /// Unless you really know, what you are doing, you should rather use the higher order access
212        /// methods provided by ILArray&lt;T>!</para>
213        /// <para>Unlike (almost) all other member function of an array, this function
214        /// does not keep track of internal memory management. It means, the storage which this array is based
215        /// upon, will not be set free after the function returns. You (as the user of the array) will have to pay
216        /// attention yourself, when to call dispose on the array - if necessary. Also, for elements of reference
217        /// types (e.g. ILCell), retrieving and storing elements from/into the System.Array directly does
218        /// not simulate a value semantic as all other functions do! This means, references are copied. Attention
219        /// must be paid to dereference / clone elements accordingly. </para></remarks>
220        public ElementType[] GetArrayForWrite() {
221            return Storage.GetArrayForWrite();
222        }
223        /// <summary>
224        /// Enumerator returning elements as ElementType
225        /// </summary>
226        /// <returns>Enumerator</returns>
227        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops.
228        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator
229        /// is compatible with ILNumerics memory management.</para></remarks>
230        /// <example><code>ILArray&lt;double&gt; A = rand(5,4,6);
231        /// foreach (double element in A) {
232        ///     // all elements are scalar double values
233        ///     String.Format("Element: {0} ", element);
234        ///     // Note: 'element' cannot be used to alter the collection!
235        /// } </code>
236        /// </example>
237        public override IEnumerator<ElementType> GetEnumerator() {
238            ElementType[] values = GetArrayForRead();
239            int len = Size.NumberOfElements;
240            for (int i = 0; i < len; i++)
241                yield return values[i];
242        }
243        /// <summary>
244        /// Gives away internal storage for further use (e.g. in ILArray), disposes this array
245        /// </summary>
246        /// <returns>Internal storage</returns>
247        internal ILDenseStorage<ElementType> GiveStorageAwayOrClone() {
248            if (m_scopeCounter <= 0) {
249                ILDenseStorage<ElementType> ret = Storage;
250                m_storage = null;
251                return ret;
252            } else {
253                return (ILDenseStorage<ElementType>)Storage.Clone();
254            }
255        }
256        /// <summary>
257        /// Create replication of this array
258        /// </summary>
259        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is
260        /// less than the number of dimensions in this array, the trailing dimensions will
261        /// be set to 1 (singleton dimensions). On the other hand, if the number specified
262        /// is larger then the number of dimension stored inside the storge the resulting
263        /// storage will get its number of dimensions extended accordingly. </param>
264        /// <returns>Array being created by multiple replications of this array along
265        /// arbitrary dimensions according to <paramref name="dims"/></returns>
266        internal ILRetArray<ElementType> Repmat(params int[] dims) {
267            return new ILRetArray<ElementType>(Storage.Repmat(dims));
268        }
269        /// <summary>
270        /// Reshaped copy of this array
271        /// </summary>
272        /// <param name="dimensions">New dimensions of the array</param>
273        /// <returns>Reshaped copy of the array</returns>
274        /// <remarks><para>The current instance will not be changed. A new storage is created, having
275        /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
276        /// </remarks>
277        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in <paramref name="dimensions"/>
278        /// do not match the number of elements in this array.</exception>
279        public ILRetArray<ElementType> Reshape(ILSize dimensions) {
280            using (ILScope.Enter()) {
281                ILArray<ElementType> ret = C;
282                ret.Storage.Reshape(dimensions);
283                return ret;
284            }
285        }
286        /// <summary>
287        /// Reshaped copy of this array
288        /// </summary>
289        /// <param name="dimensions">New dimensions of the array</param>
290        /// <returns>Reshaped copy of the array</returns>
291        /// <remarks><para>The current instance will not be changed. A new array is created, having
292        /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
293        /// </remarks>
294        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 'newDimension'
295        /// do not match the number of elements in this array.</exception>
296        public ILRetArray<ElementType> Reshape(params int[] dimensions) {
297            return Reshape(new ILSize(dimensions));
298        }
299        /// <summary>
300        /// Subarray creation
301        /// </summary>
302        /// <param name="size">Range specification, defining the size of the subarray</param>
303        /// <returns>Subarray as copy of a part of this array</returns>
304        /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
305        public ILRetArray<ElementType> Subarray(params ILBaseArray[] size) {
306            using (ILScope.Enter(size))
307                return new ILRetArray<ElementType>(Storage.Subarray(size));
308        }
309        /// <summary>
310        /// Create array from this array and shift dimensions
311        /// </summary>
312        /// <param name="shift">Number of dimensions to shift</param>
313        /// <returns>Shifted version of this array</returns>
314        /// <remarks><para>The shift is done 'to the left':</para>
315        /// <example><code>ILArray&lt;double> A = zeros(2,4);
316        /// ILArray&lt;double> B = A.Shifted(1);
317        /// // B is now: &lt;double> [4,2]
318        ///
319        /// ILArray&lt;double> C = zeros(2,4,3);
320        /// ILArray&lt;double> D = C.Shifted(1);
321        /// // D is now: &lt;double> [4,3,2]
322        /// </code></example>
323        /// <para>The dimensions are shifted circulary to the left. This
324        /// can be imagined as removing the first dimensions from the beginning of the list of
325        /// dimensions and "append" them to the end in a ringbuffer style.</para>
326        /// <para>For dimension shifts of '1', you may consider using the
327        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
328        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
329        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
330        public ILRetArray<ElementType> Shifted(int shift) {
331            return new ILRetArray<ElementType>(Storage.ShiftDimensions(shift));
332        }
333        /// <summary>
334        /// Send values of this instance to stream.
335        /// </summary>
336        /// <param name="stream">Stream to write the values into.</param>
337        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
338        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
339        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
340        /// the values will be serialized.</param>
341        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s)
342        /// will be replaced from the format string before applying to the elements. This is done to
343        /// prevent the format from breaking the 'page' style of the output.</para>
344        /// <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
345        /// 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
346        /// create a collection of arrays and write the MatFile to stream.</para></remarks>
347        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
348            try {
349                int len;
350                switch (method) {
351                    case ILArrayStreamSerializationFlags.Serial:
352                        len = Size.NumberOfElements;
353                        using (TextWriter tw = new StreamWriter(stream)) {
354                            for (int i = 0; i < len; i++) {
355                                tw.Write(format, GetValue(i));
356                            }
357                        }
358                        break;
359                    case ILArrayStreamSerializationFlags.Formatted:
360                        format = format.Replace(Environment.NewLine, "");
361                        ILDenseStorage<ElementType> temp = this.Storage.ShiftDimensions(1);
362                        //len = Dimensions.NumberOfElements / Dimensions[1];
363                        using (TextWriter tw = new StreamWriter(stream)) {
364                            tw.Write(temp.ValuesToString(0));
365                        }
366                        break;
367                    case ILArrayStreamSerializationFlags.Matlab:
368                        ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
369                        mf.Write(stream);
370                        break;
371                }
372            } catch (Exception e) {
373                throw new ILException("ToStream: Could not serialize to stream.", e);
374            }
375        }
376        /// <summary>
377        /// Give that storage away for in-place operations, if possible (depends on scope and temp type of array)
378        /// </summary>
379        /// <returns>true if the storage of the array is about to get disposed anyway</returns>
380        /// <remarks>The function investigates the state of the array. If this is a temporary array in
381        /// the outer most scope, it would get disposed after the </remarks>
382        internal bool TryGetStorage4InplaceOp(out ElementType[] array) {
383            // check if this array is yet to be available
384            if (!Settings.AllowInArrayAssignments && m_isTempArray && m_scopeCounter <= 1) {
385                // it's efficient only if we dont have to make a copy of the underlying array
386                if (Storage.ReferenceCount == 1) {
387                    ILDenseStorage<ElementType> storage = Storage;
388                    m_storage = null;
389                    array = storage.GetArrayForWrite();
390                    return true;
391                }
392            }
393            array = null;
394            return false;
395        }
396        #endregion
397    }
398}
Note: See TracBrowser for help on using the repository browser.