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 ILNumerics;
|
---|
42 | using ILNumerics.Misc;
|
---|
43 | using ILNumerics.Storage;
|
---|
44 | using ILNumerics.Native;
|
---|
45 | using System.Runtime.Serialization;
|
---|
46 | using System.Runtime.Serialization.Formatters.Binary;
|
---|
47 | using System.IO;
|
---|
48 | using System.Text;
|
---|
49 | using System.Collections.Generic;
|
---|
50 | using System.Collections;
|
---|
51 |
|
---|
52 | namespace ILNumerics {
|
---|
53 | /// <summary>
|
---|
54 | /// Base type for all arrays in ILNumerics
|
---|
55 | /// </summary>
|
---|
56 | /// <remarks>All numerical arrays derive from ILBaseArray. ILBaseArrays itself
|
---|
57 | /// cannot be instantiated. Currently, only ILArray<![CDATA[<>]]> exist, which describe
|
---|
58 | /// a rectangular array as full (solid) or referencing array. There are plans to
|
---|
59 | /// extend the collection of derived types to encompass triangular, diagonal and sparse arrays.
|
---|
60 | /// </remarks>
|
---|
61 | [Serializable]
|
---|
62 | public abstract class ILBaseArray : IDisposable {
|
---|
63 |
|
---|
64 | #region attributes
|
---|
65 | /// <summary>
|
---|
66 | /// Name of this array
|
---|
67 | /// </summary>
|
---|
68 | protected String m_name = "";
|
---|
69 | internal ILStorage m_storage;
|
---|
70 | internal int m_scopeCounter = 0;
|
---|
71 | internal bool m_isTempArray;
|
---|
72 | #endregion
|
---|
73 |
|
---|
74 | #region properties
|
---|
75 | internal int ScopeID {
|
---|
76 | get { return m_scopeCounter; }
|
---|
77 |
|
---|
78 | }
|
---|
79 | internal bool IsDisposed {
|
---|
80 | get { return m_storage == null || m_storage.IsDisposed; }
|
---|
81 | }
|
---|
82 |
|
---|
83 | internal ILStorage Storage {
|
---|
84 | get { return m_storage; }
|
---|
85 | }
|
---|
86 |
|
---|
87 | /// <summary>
|
---|
88 | /// Size descriptor specification
|
---|
89 | /// </summary>
|
---|
90 | public virtual ILSize Size {
|
---|
91 | get {
|
---|
92 | return Storage.Size;
|
---|
93 | }
|
---|
94 | }
|
---|
95 | /// <summary>
|
---|
96 | /// [deprecated] Use 'Size' as size descriptor!
|
---|
97 | /// </summary>
|
---|
98 | [Obsolete("Use 'Size' instead!")]
|
---|
99 | public ILSize Dimensions {
|
---|
100 | get {
|
---|
101 | return Size;
|
---|
102 | }
|
---|
103 | }
|
---|
104 | /// <summary>
|
---|
105 | /// Size descriptor shortcut
|
---|
106 | /// </summary>
|
---|
107 | public virtual ILSize S {
|
---|
108 | get {
|
---|
109 | return Storage.Size;
|
---|
110 | }
|
---|
111 | }
|
---|
112 | /// <summary>
|
---|
113 | /// [deprecated] Use 'S' as size descriptor!
|
---|
114 | /// </summary>
|
---|
115 | [Obsolete("Use S instead!")]
|
---|
116 | public virtual ILSize D {
|
---|
117 | get {
|
---|
118 | return S;
|
---|
119 | }
|
---|
120 | }
|
---|
121 | /// <summary>
|
---|
122 | /// Length of the longest dimension of this instance
|
---|
123 | /// </summary>
|
---|
124 | /// <remarks>This property is readonly.</remarks>
|
---|
125 | public virtual int Length {
|
---|
126 | get {
|
---|
127 | return Size.Longest;
|
---|
128 | }
|
---|
129 | }
|
---|
130 | /// <summary>
|
---|
131 | /// Gets the name of this array or sets it
|
---|
132 | /// </summary>
|
---|
133 | public String Name {
|
---|
134 | get {
|
---|
135 | return m_name;
|
---|
136 | }
|
---|
137 | set {
|
---|
138 | m_name = value;
|
---|
139 | }
|
---|
140 | }
|
---|
141 | /// <summary>
|
---|
142 | /// Test if this instance is a scalar
|
---|
143 | /// </summary>
|
---|
144 | /// <remarks>This attribute is readonly. It returns: Size.NumberOfElements == 1.</remarks>
|
---|
145 | public virtual bool IsScalar {
|
---|
146 | get {
|
---|
147 | return Size.NumberOfElements == 1;
|
---|
148 | }
|
---|
149 | }
|
---|
150 | /// <summary>
|
---|
151 | /// Test if this instance is a matrix
|
---|
152 | /// </summary>
|
---|
153 | /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b>
|
---|
154 | /// dimensions must equal 2. This attribute is readonly.</remarks>
|
---|
155 | public virtual bool IsMatrix {
|
---|
156 | get {
|
---|
157 | if (Size.NumberOfDimensions == 2)
|
---|
158 | return true;
|
---|
159 | return (Size.Squeeze().NumberOfDimensions == 2);
|
---|
160 | }
|
---|
161 | }
|
---|
162 | /// <summary>
|
---|
163 | /// Test if this array is a vector
|
---|
164 | /// </summary>
|
---|
165 | /// <remarks>In order for an array to be a vector the number of <b>non singleton</b>
|
---|
166 | /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore
|
---|
167 | /// it is not sufficient to test for the number of dimensions, but to take the number of
|
---|
168 | /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
|
---|
169 | public virtual bool IsVector {
|
---|
170 | get {
|
---|
171 | return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
|
---|
172 | }
|
---|
173 | }
|
---|
174 | /// <summary>
|
---|
175 | /// Test if this array instance is a row vector
|
---|
176 | /// </summary>
|
---|
177 | public virtual bool IsRowVector {
|
---|
178 | get {
|
---|
179 | return Size[0] == 1 && Size.NumberOfDimensions == 2;
|
---|
180 | }
|
---|
181 | }
|
---|
182 | /// <summary>
|
---|
183 | /// Test if this array instance is a column vector
|
---|
184 | /// </summary>
|
---|
185 | public virtual bool IsColumnVector {
|
---|
186 | get {
|
---|
187 | return Size[1] == 1 && Size.NumberOfDimensions == 2;;
|
---|
188 | }
|
---|
189 | }
|
---|
190 | /// <summary>
|
---|
191 | /// Test if this instance is an empty array (number of elements stored = 0)
|
---|
192 | /// </summary>
|
---|
193 | public virtual bool IsEmpty {
|
---|
194 | get {
|
---|
195 | return Size.NumberOfElements == 0;
|
---|
196 | }
|
---|
197 | }
|
---|
198 | #endregion
|
---|
199 |
|
---|
200 | #region constructors
|
---|
201 | internal ILBaseArray(ILStorage storage, bool isTempArray) {
|
---|
202 | m_storage = storage;
|
---|
203 | m_isTempArray = isTempArray;
|
---|
204 | }
|
---|
205 | /// <summary>
|
---|
206 | /// Implicit cast from scalar of typeof(a) to <c>ILRetArray<typeof(A)></c>
|
---|
207 | /// </summary>
|
---|
208 | /// <param name="a">Input scalar</param>
|
---|
209 | /// <returns>A ILRetArray of same type as <paramref name="a"/> and size 1x1</returns>
|
---|
210 | public static implicit operator ILBaseArray(double a) {
|
---|
211 | return new ILRetArray<double>(new double[] { a }, ILSize.Scalar1_1);
|
---|
212 | }
|
---|
213 | /// <summary>
|
---|
214 | /// Implicit cast from scalar of typeof(A) to ILRetArray<typeof(A)>
|
---|
215 | /// </summary>
|
---|
216 | /// <param name="a">Input scalar</param>
|
---|
217 | /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
|
---|
218 | public static implicit operator ILBaseArray(complex a) {
|
---|
219 | return new ILRetArray<complex>(new complex[] { a, 0 }, ILSize.Scalar1_1);
|
---|
220 | }
|
---|
221 | /// <summary>
|
---|
222 | /// Implicit cast from scalar of typeof(A) to ILRetArray<typeof(A)>
|
---|
223 | /// </summary>
|
---|
224 | /// <param name="a">Input scalar</param>
|
---|
225 | /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
|
---|
226 | public static implicit operator ILBaseArray(fcomplex a) {
|
---|
227 | return new ILRetArray<fcomplex>(new fcomplex[] { a, 0 }, ILSize.Scalar1_1);
|
---|
228 | }
|
---|
229 | /// <summary>
|
---|
230 | /// Implicit cast from scalar of typeof(A) to ILRetArray<typeof(A)>
|
---|
231 | /// </summary>
|
---|
232 | /// <param name="s">Input scalar</param>
|
---|
233 | /// <returns>A ILRetArray of same type as <paramref name="s"/> and size 1x1</returns>
|
---|
234 | public static implicit operator ILBaseArray(string s) {
|
---|
235 | return new ILRetArray<string>(new string[] { s }, ILSize.Scalar1_1);
|
---|
236 | }
|
---|
237 | //public static implicit operator ILBaseArray(string[] arr) {
|
---|
238 | // return new ILRetArray<string>(new string[] { String.Join(";", arr) }, ILSize.Scalar1_1);
|
---|
239 | //}
|
---|
240 | /// <summary>
|
---|
241 | /// Implicit cast from scalar of typeof(A) to ILRetArray<typeof(A)>
|
---|
242 | /// </summary>
|
---|
243 | /// <param name="a">Input scalar</param>
|
---|
244 | /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
|
---|
245 | public static implicit operator ILBaseArray(double[] a) {
|
---|
246 | if (a == null || a.Length == 0) {
|
---|
247 | return new ILRetArray<double>(ILSize.Empty00);
|
---|
248 | }
|
---|
249 | ILCell ret = new ILCell(1,a.Length);
|
---|
250 | for (int i = 0; i < a.Length; i++) {
|
---|
251 | ret.SetValue(new ILRetArray<double>(new double[] { a[i] }, ILSize.Scalar1_1),0,i);
|
---|
252 | }
|
---|
253 | //ret.SetValue("int[]",1,0);
|
---|
254 | return ret;
|
---|
255 | }
|
---|
256 | //public static implicit operator ILBaseArray(int[] a) {
|
---|
257 | // if (a == null || a.Length == 0) {
|
---|
258 | // return new ILRetArray<int>(ILSize.Empty00);
|
---|
259 | // }
|
---|
260 | // ILCell ret = new ILCell(1,a.Length);
|
---|
261 | // for (int i = 0; i < a.Length; i++) {
|
---|
262 | // ret.SetValue(new ILRetArray<int>(new int[] { a[i] }, ILSize.Scalar1_1),0,i);
|
---|
263 | // }
|
---|
264 | // //ret.SetValue("int[]",1,0);
|
---|
265 | // return ret;
|
---|
266 | //}
|
---|
267 | #endregion
|
---|
268 |
|
---|
269 | #region virtual
|
---|
270 | /// <summary>
|
---|
271 | /// Compare elements and shape of this array with another array
|
---|
272 | /// </summary>
|
---|
273 | /// <param name="A">Other array</param>
|
---|
274 | /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
|
---|
275 | /// <remarks><para>'Equals' accepts two vectors even if the orientations do not match. Therefore, a row vector
|
---|
276 | /// with the same element values than another column vector would be considered equal to each other.</para></remarks>
|
---|
277 | public override bool Equals(object A) {
|
---|
278 | ILBaseArray baseArray = A as ILBaseArray;
|
---|
279 | if (baseArray != null) {
|
---|
280 | return Storage.Equals(baseArray.Storage);
|
---|
281 | }
|
---|
282 | if (IsScalar && A is System.ValueType) {
|
---|
283 | return String.Equals(A.ToString(),Storage.GetValue(0).ToString());
|
---|
284 | }
|
---|
285 | return false;
|
---|
286 | }
|
---|
287 | /// <summary>
|
---|
288 | /// Generate a hash code based on the current arrays values
|
---|
289 | /// </summary>
|
---|
290 | /// <returns>Hash code</returns>
|
---|
291 | /// <remarks>The hashcode is created by taking the values currently stored in the array into account.
|
---|
292 | /// Therefore, the function iterates over all elements in the array - which makes it somehow an expensive
|
---|
293 | /// operation. Take this into account, if you consider using large arrays in collections like dictionaries
|
---|
294 | /// or hashtables, which make great use of hash codes.</remarks>
|
---|
295 | public override int GetHashCode() {
|
---|
296 | return Storage.GetHashCode();
|
---|
297 | }
|
---|
298 |
|
---|
299 | internal virtual bool EnterScope() {
|
---|
300 | if (m_scopeCounter < 2) {
|
---|
301 | m_scopeCounter++;
|
---|
302 | return true;
|
---|
303 | }
|
---|
304 | return false;
|
---|
305 | }
|
---|
306 | internal virtual void LeaveScope() {
|
---|
307 | if (--m_scopeCounter <= 0) {
|
---|
308 | Dispose();
|
---|
309 | }
|
---|
310 | }
|
---|
311 |
|
---|
312 | #endregion
|
---|
313 |
|
---|
314 | #region abstract interface
|
---|
315 | /// <summary>
|
---|
316 | /// Clone this array (shallow)
|
---|
317 | /// </summary>
|
---|
318 | /// <returns>ILBaseArray as new representation of this storages data.</returns>
|
---|
319 | /// <remarks>The object returned will be of the same size than this array.
|
---|
320 | /// This this is a 'shallow' copy only! I.e., if elements are copied only. If they are
|
---|
321 | /// references to any objects, those objects are not replicated.</remarks>
|
---|
322 | internal abstract ILBaseArray Clone();
|
---|
323 |
|
---|
324 | /// <summary>
|
---|
325 | /// Determine if this array is of complex inner type.
|
---|
326 | /// </summary>
|
---|
327 | public abstract bool IsComplex {
|
---|
328 | get;
|
---|
329 | }
|
---|
330 | /// <summary>
|
---|
331 | /// Determine if this array is of numeric inner type.
|
---|
332 | /// </summary>
|
---|
333 | public abstract bool IsNumeric {
|
---|
334 | get;
|
---|
335 | }
|
---|
336 | /// <summary>
|
---|
337 | /// Print values of this instance to a stream.
|
---|
338 | /// </summary>
|
---|
339 | /// <param name="outStream">Stream to write the values into.</param>
|
---|
340 | /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
|
---|
341 | /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
|
---|
342 | /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way
|
---|
343 | /// the values will be serialized.</param>
|
---|
344 | /// <remarks><para>If method 'Formatted' is used, any occurences of NewLine character(s)
|
---|
345 | /// will be replaced from the format string before applying to the elements. This is done to
|
---|
346 | /// prevent the format from breaking the 'page' style for the output.</para>
|
---|
347 | /// <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
|
---|
348 | /// the 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
|
---|
349 | /// create a collection of arrays and write the MatFile to stream.</para></remarks>
|
---|
350 | public abstract void ToStream(Stream outStream, string format, ILArrayStreamSerializationFlags method);
|
---|
351 |
|
---|
352 | /// <summary>
|
---|
353 | /// Convert to string
|
---|
354 | /// </summary>
|
---|
355 | /// <returns>String representation of content</returns>
|
---|
356 | public override string ToString() {
|
---|
357 | return ToString(0);
|
---|
358 | }
|
---|
359 | /// <summary>
|
---|
360 | /// Convert to string with limited length
|
---|
361 | /// </summary>
|
---|
362 | /// <param name="maxLength">Maximal length of returned string; set to 0 to not limit result</param>
|
---|
363 | /// <returns>String representation of content</returns>
|
---|
364 | public virtual string ToString(int maxLength) {
|
---|
365 | string ret = ShortInfo();
|
---|
366 | if (m_storage.Size.NumberOfElements > 1)
|
---|
367 | ret += Environment.NewLine + Storage.ValuesToString(maxLength);
|
---|
368 | return ret;
|
---|
369 | }
|
---|
370 | /// <summary>
|
---|
371 | /// Short textual summary of this instance, used for debug output
|
---|
372 | /// </summary>
|
---|
373 | /// <returns>String representation of type and size</returns>
|
---|
374 | /// <remarks>The type of elements and the size of the array are displayed. If the array
|
---|
375 | /// is scalar, its value is displayed next to the type.</remarks>
|
---|
376 | public virtual String ShortInfo() {
|
---|
377 | return Storage.ShortInfo();
|
---|
378 | }
|
---|
379 | /// <summary>
|
---|
380 | /// Dispose this array and all its content
|
---|
381 | /// </summary>
|
---|
382 | public void Dispose() {
|
---|
383 | if (IsDisposed) return;
|
---|
384 | if (Storage != null) {
|
---|
385 | Storage.Dispose();
|
---|
386 | }
|
---|
387 | }
|
---|
388 | #endregion
|
---|
389 |
|
---|
390 | }
|
---|
391 |
|
---|
392 | } |
---|