Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eq.cs @ 11194

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

#1967: ILNumerics source for experimentation

File size: 98.6 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
40
41
42using System;
43using System.Collections.Generic;
44using System.Text;
45using System.Runtime.InteropServices;
46using ILNumerics.Storage;
47using ILNumerics.Misc;
48using ILNumerics.Native;
49using ILNumerics.Exceptions;
50
51namespace ILNumerics {
52
53    public partial class ILMath {
54
55
56        /// <summary>Elementwise logical 'equal' operator</summary>
57        /// <param name="A">Input array A</param>
58        /// <param name="B">Input array B</param>
59        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
60        /// <remarks><para>On empty input an empty array will be returned.</para>
61        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
62        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
63        public unsafe static ILRetLogical  eq(ILInArray<double> A, ILInArray<double> B) {
64            using (ILScope.Enter(A, B)) {
65                int outLen;
66                BinOpItMode mode;
67                byte[] retArr;
68               
69                double[] arrA = A.GetArrayForRead();
70               
71                double[] arrB = B.GetArrayForRead();
72                ILSize outDims;
73                if (A.IsScalar) {
74                    if (B.IsScalar) {
75                       
76                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
77                    } else if (B.IsEmpty) {
78                        return new ILRetLogical(B.Size);
79                    } else {
80                        outLen = B.S.NumberOfElements;
81                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
82                        mode = BinOpItMode.SAN;
83                    }
84                    outDims = B.Size;
85                } else {
86                    outDims = A.Size;
87                    if (B.IsScalar) {
88                        if (A.IsEmpty) {
89                            return new ILRetLogical(A.Size);
90                        }
91                        outLen = A.S.NumberOfElements;
92                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
93                        mode = BinOpItMode.ASN;
94                    } else {
95                        // array + array
96                        if (!A.Size.IsSameSize(B.Size)) {
97                            return  eqEx(A,B);
98                        }
99                        outLen = A.S.NumberOfElements;
100                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
101                        mode = BinOpItMode.AAN;
102                    }
103                }
104                int workerCount = 1;
105                Action<object> worker = data => {
106                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
107                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
108                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
109                     double scalar;
110                    cLast = cp + range.Item2;
111                    #region loops
112                    switch (mode) {
113                        case BinOpItMode.AAN:
114                             double* ap = ((double*)range.Item3 + range.Item1);
115                             double* bp = ((double*)range.Item4 + range.Item1);
116                            while (cp < cLast) {
117                               
118                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
119                                cp++;
120                                ap++;
121                                bp++;
122                            }
123                            break;
124                        case BinOpItMode.ASN:
125                            ap = ((double*)range.Item3 + range.Item1);
126                            scalar = *((double*)range.Item4);
127                            while (cp < cLast) {
128                               
129                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
130                                cp++;
131                                ap++;
132
133                            }
134                            break;
135                        case BinOpItMode.SAN:
136                            scalar = *((double*)range.Item3);
137                            bp = ((double*)range.Item4 + range.Item1);
138                            while (cp < cLast) {
139                               
140                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
141                                cp++;
142                                bp++;
143                            }
144                            break;
145                        default:
146                            break;
147                    }
148                    #endregion
149                    System.Threading.Interlocked.Decrement(ref workerCount);
150                };
151
152                #region do the work
153                fixed (double* arrAP = arrA)
154                fixed (double* arrBP = arrB)
155                fixed (byte* retArrP = retArr) {
156                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
157                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
158                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
159                            workItemLength = outLen / workItemCount;
160                        } else {
161                            workItemLength = outLen / 2;
162                            workItemCount = 2;
163                        }
164                    } else {
165                        workItemLength = outLen;
166                        workItemCount = 1;
167                    }
168
169                    for (; i < workItemCount - 1; i++) {
170                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
171                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
172                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
173                        System.Threading.Interlocked.Increment(ref workerCount);
174                        ILThreadPool.QueueUserWorkItem(i, worker, range);
175                    }
176                    // the last (or may the only) chunk is done right here
177                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
178                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
179                    ILThreadPool.Wait4Workers(ref workerCount);
180                }
181
182                #endregion
183                return new ILRetLogical(retArr, outDims);
184            }
185        }
186
187        private static unsafe ILRetLogical  eqEx(ILInArray<double> A, ILInArray<double> B) {
188            using (ILScope.Enter(A, B)) {
189                #region parameter checking
190                if (isnull(A) || isnull(B))
191                    return new ILRetLogical(ILSize.Empty00);
192                if (A.IsEmpty) {
193                    return new ILRetLogical(B.S);
194                } else if (B.IsEmpty) {
195                    return new ILRetLogical(A.S);
196                }
197                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
198                //    return add(A,B);
199                int dim = -1;
200                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
201                    if (A.S[l] != B.S[l]) {
202                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
203                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
204                        }
205                        dim = l;
206                    }
207                }
208                if (dim > 1)
209                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
210                #endregion
211
212                #region parameter preparation
213                byte[] retArr;
214               
215                double[] arrA = A.GetArrayForRead();
216               
217                double[] arrB = B.GetArrayForRead();
218                ILSize outDims;
219                BinOptItExMode mode;
220                int arrInc = 0;
221                int arrStepInc = 0;
222                int dimLen = 0;
223                if (A.IsVector) {
224                    outDims = B.S;
225                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
226                    mode = BinOptItExMode.VAN;
227                    dimLen = A.Length;
228                } else if (B.IsVector) {
229                    outDims = A.S;
230                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
231                    mode = BinOptItExMode.AVN;
232                    dimLen = B.Length;
233                } else {
234                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
235                }
236                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
237                arrStepInc = outDims.SequentialIndexDistance(dim);
238                #endregion
239
240                #region worker loops definition
241                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
242                int workerCount = 1;
243                Action<object> worker = data => {
244                    // expects: iStart, iLen, ap, bp, cp
245                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
246                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
247                   
248                    double* ap;
249                   
250                    double* bp;
251                    byte* cp;
252                    switch (mode) {
253                        case BinOptItExMode.VAN:
254                            for (int s = 0; s < range.Item2; s++) {
255                                ap = (double*)range.Item3;
256                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
257                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
258                                for (int l = 0; l < dimLen; l++) {
259                                   
260                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
261                                    ap++;
262                                    bp += arrInc;
263                                    cp += arrInc;
264                                }
265                            }
266                            break;
267                        case BinOptItExMode.AVN:
268                            for (int s = 0; s < range.Item2; s++) {
269                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
270                                bp = (double*)range.Item4;
271                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
272                                for (int l = 0; l < dimLen; l++) {
273                                   
274                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
275                                    ap += arrInc;
276                                    bp++;
277                                    cp += arrInc;
278                                }
279                            }
280                            break;
281                    }
282                    System.Threading.Interlocked.Decrement(ref workerCount);
283                };
284                #endregion
285
286                #region work distribution
287                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
288                int outLen = outDims.NumberOfElements;
289                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
290                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
291                        workItemLength = outLen / dimLen / workItemCount;
292                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
293                    } else {
294                        workItemLength = outLen / dimLen / 2;
295                        workItemCount = 2;
296                    }
297                } else {
298                    workItemLength = outLen / dimLen;
299                    workItemCount = 1;
300                }
301
302                fixed ( double* arrAP = arrA)
303                fixed ( double* arrBP = arrB)
304                fixed (byte* retArrP = retArr) {
305
306                    for (; i < workItemCount - 1; i++) {
307                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
308                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
309                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
310                        System.Threading.Interlocked.Increment(ref workerCount);
311                        ILThreadPool.QueueUserWorkItem(i, worker, range);
312                    }
313                    // the last (or may the only) chunk is done right here
314                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
315                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
316                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
317
318                    ILThreadPool.Wait4Workers(ref workerCount);
319                }
320                #endregion
321
322                return new ILRetLogical(retStorage);
323            }
324        }
325
326
327#region HYCALPER AUTO GENERATED CODE
328
329        /// <summary>Elementwise logical 'equal' operator</summary>
330        /// <param name="A">Input array A</param>
331        /// <param name="B">Input array B</param>
332        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
333        /// <remarks><para>On empty input an empty array will be returned.</para>
334        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
335        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
336        public unsafe static ILRetLogical  eq(ILInArray<Int64> A, ILInArray<Int64> B) {
337            using (ILScope.Enter(A, B)) {
338                int outLen;
339                BinOpItMode mode;
340                byte[] retArr;
341               
342                Int64[] arrA = A.GetArrayForRead();
343               
344                Int64[] arrB = B.GetArrayForRead();
345                ILSize outDims;
346                if (A.IsScalar) {
347                    if (B.IsScalar) {
348                       
349                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
350                    } else if (B.IsEmpty) {
351                        return new ILRetLogical(B.Size);
352                    } else {
353                        outLen = B.S.NumberOfElements;
354                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
355                        mode = BinOpItMode.SAN;
356                    }
357                    outDims = B.Size;
358                } else {
359                    outDims = A.Size;
360                    if (B.IsScalar) {
361                        if (A.IsEmpty) {
362                            return new ILRetLogical(A.Size);
363                        }
364                        outLen = A.S.NumberOfElements;
365                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
366                        mode = BinOpItMode.ASN;
367                    } else {
368                        // array + array
369                        if (!A.Size.IsSameSize(B.Size)) {
370                            return  eqEx(A,B);
371                        }
372                        outLen = A.S.NumberOfElements;
373                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
374                        mode = BinOpItMode.AAN;
375                    }
376                }
377                int workerCount = 1;
378                Action<object> worker = data => {
379                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
380                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
381                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
382                    Int64 scalar;
383                    cLast = cp + range.Item2;
384                    #region loops
385                    switch (mode) {
386                        case BinOpItMode.AAN:
387                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
388                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
389                            while (cp < cLast) {
390                               
391                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
392                                cp++;
393                                ap++;
394                                bp++;
395                            }
396                            break;
397                        case BinOpItMode.ASN:
398                            ap = ((Int64*)range.Item3 + range.Item1);
399                            scalar = *((Int64*)range.Item4);
400                            while (cp < cLast) {
401                               
402                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
403                                cp++;
404                                ap++;
405
406                            }
407                            break;
408                        case BinOpItMode.SAN:
409                            scalar = *((Int64*)range.Item3);
410                            bp = ((Int64*)range.Item4 + range.Item1);
411                            while (cp < cLast) {
412                               
413                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
414                                cp++;
415                                bp++;
416                            }
417                            break;
418                        default:
419                            break;
420                    }
421                    #endregion
422                    System.Threading.Interlocked.Decrement(ref workerCount);
423                };
424
425                #region do the work
426                fixed (Int64* arrAP = arrA)
427                fixed (Int64* arrBP = arrB)
428                fixed (byte* retArrP = retArr) {
429                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
430                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
431                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
432                            workItemLength = outLen / workItemCount;
433                        } else {
434                            workItemLength = outLen / 2;
435                            workItemCount = 2;
436                        }
437                    } else {
438                        workItemLength = outLen;
439                        workItemCount = 1;
440                    }
441
442                    for (; i < workItemCount - 1; i++) {
443                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
444                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
445                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
446                        System.Threading.Interlocked.Increment(ref workerCount);
447                        ILThreadPool.QueueUserWorkItem(i, worker, range);
448                    }
449                    // the last (or may the only) chunk is done right here
450                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
451                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
452                    ILThreadPool.Wait4Workers(ref workerCount);
453                }
454
455                #endregion
456                return new ILRetLogical(retArr, outDims);
457            }
458        }
459
460        private static unsafe ILRetLogical  eqEx(ILInArray<Int64> A, ILInArray<Int64> B) {
461            using (ILScope.Enter(A, B)) {
462                #region parameter checking
463                if (isnull(A) || isnull(B))
464                    return new ILRetLogical(ILSize.Empty00);
465                if (A.IsEmpty) {
466                    return new ILRetLogical(B.S);
467                } else if (B.IsEmpty) {
468                    return new ILRetLogical(A.S);
469                }
470                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
471                //    return add(A,B);
472                int dim = -1;
473                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
474                    if (A.S[l] != B.S[l]) {
475                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
476                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
477                        }
478                        dim = l;
479                    }
480                }
481                if (dim > 1)
482                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
483                #endregion
484
485                #region parameter preparation
486                byte[] retArr;
487               
488                Int64[] arrA = A.GetArrayForRead();
489               
490                Int64[] arrB = B.GetArrayForRead();
491                ILSize outDims;
492                BinOptItExMode mode;
493                int arrInc = 0;
494                int arrStepInc = 0;
495                int dimLen = 0;
496                if (A.IsVector) {
497                    outDims = B.S;
498                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
499                    mode = BinOptItExMode.VAN;
500                    dimLen = A.Length;
501                } else if (B.IsVector) {
502                    outDims = A.S;
503                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
504                    mode = BinOptItExMode.AVN;
505                    dimLen = B.Length;
506                } else {
507                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
508                }
509                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
510                arrStepInc = outDims.SequentialIndexDistance(dim);
511                #endregion
512
513                #region worker loops definition
514                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
515                int workerCount = 1;
516                Action<object> worker = data => {
517                    // expects: iStart, iLen, ap, bp, cp
518                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
519                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
520                   
521                    Int64* ap;
522                   
523                    Int64* bp;
524                    byte* cp;
525                    switch (mode) {
526                        case BinOptItExMode.VAN:
527                            for (int s = 0; s < range.Item2; s++) {
528                                ap = (Int64*)range.Item3;
529                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
530                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
531                                for (int l = 0; l < dimLen; l++) {
532                                   
533                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
534                                    ap++;
535                                    bp += arrInc;
536                                    cp += arrInc;
537                                }
538                            }
539                            break;
540                        case BinOptItExMode.AVN:
541                            for (int s = 0; s < range.Item2; s++) {
542                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
543                                bp = (Int64*)range.Item4;
544                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
545                                for (int l = 0; l < dimLen; l++) {
546                                   
547                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
548                                    ap += arrInc;
549                                    bp++;
550                                    cp += arrInc;
551                                }
552                            }
553                            break;
554                    }
555                    System.Threading.Interlocked.Decrement(ref workerCount);
556                };
557                #endregion
558
559                #region work distribution
560                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
561                int outLen = outDims.NumberOfElements;
562                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
563                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
564                        workItemLength = outLen / dimLen / workItemCount;
565                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
566                    } else {
567                        workItemLength = outLen / dimLen / 2;
568                        workItemCount = 2;
569                    }
570                } else {
571                    workItemLength = outLen / dimLen;
572                    workItemCount = 1;
573                }
574
575                fixed ( Int64* arrAP = arrA)
576                fixed ( Int64* arrBP = arrB)
577                fixed (byte* retArrP = retArr) {
578
579                    for (; i < workItemCount - 1; i++) {
580                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
581                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
582                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
583                        System.Threading.Interlocked.Increment(ref workerCount);
584                        ILThreadPool.QueueUserWorkItem(i, worker, range);
585                    }
586                    // the last (or may the only) chunk is done right here
587                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
588                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
589                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
590
591                    ILThreadPool.Wait4Workers(ref workerCount);
592                }
593                #endregion
594
595                return new ILRetLogical(retStorage);
596            }
597        }
598
599        /// <summary>Elementwise logical 'equal' operator</summary>
600        /// <param name="A">Input array A</param>
601        /// <param name="B">Input array B</param>
602        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
603        /// <remarks><para>On empty input an empty array will be returned.</para>
604        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
605        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
606        public unsafe static ILRetLogical  eq(ILInArray<Int32> A, ILInArray<Int32> B) {
607            using (ILScope.Enter(A, B)) {
608                int outLen;
609                BinOpItMode mode;
610                byte[] retArr;
611               
612                Int32[] arrA = A.GetArrayForRead();
613               
614                Int32[] arrB = B.GetArrayForRead();
615                ILSize outDims;
616                if (A.IsScalar) {
617                    if (B.IsScalar) {
618                       
619                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
620                    } else if (B.IsEmpty) {
621                        return new ILRetLogical(B.Size);
622                    } else {
623                        outLen = B.S.NumberOfElements;
624                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
625                        mode = BinOpItMode.SAN;
626                    }
627                    outDims = B.Size;
628                } else {
629                    outDims = A.Size;
630                    if (B.IsScalar) {
631                        if (A.IsEmpty) {
632                            return new ILRetLogical(A.Size);
633                        }
634                        outLen = A.S.NumberOfElements;
635                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
636                        mode = BinOpItMode.ASN;
637                    } else {
638                        // array + array
639                        if (!A.Size.IsSameSize(B.Size)) {
640                            return  eqEx(A,B);
641                        }
642                        outLen = A.S.NumberOfElements;
643                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
644                        mode = BinOpItMode.AAN;
645                    }
646                }
647                int workerCount = 1;
648                Action<object> worker = data => {
649                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
650                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
651                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
652                    Int32 scalar;
653                    cLast = cp + range.Item2;
654                    #region loops
655                    switch (mode) {
656                        case BinOpItMode.AAN:
657                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
658                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
659                            while (cp < cLast) {
660                               
661                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
662                                cp++;
663                                ap++;
664                                bp++;
665                            }
666                            break;
667                        case BinOpItMode.ASN:
668                            ap = ((Int32*)range.Item3 + range.Item1);
669                            scalar = *((Int32*)range.Item4);
670                            while (cp < cLast) {
671                               
672                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
673                                cp++;
674                                ap++;
675
676                            }
677                            break;
678                        case BinOpItMode.SAN:
679                            scalar = *((Int32*)range.Item3);
680                            bp = ((Int32*)range.Item4 + range.Item1);
681                            while (cp < cLast) {
682                               
683                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
684                                cp++;
685                                bp++;
686                            }
687                            break;
688                        default:
689                            break;
690                    }
691                    #endregion
692                    System.Threading.Interlocked.Decrement(ref workerCount);
693                };
694
695                #region do the work
696                fixed (Int32* arrAP = arrA)
697                fixed (Int32* arrBP = arrB)
698                fixed (byte* retArrP = retArr) {
699                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
700                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
701                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
702                            workItemLength = outLen / workItemCount;
703                        } else {
704                            workItemLength = outLen / 2;
705                            workItemCount = 2;
706                        }
707                    } else {
708                        workItemLength = outLen;
709                        workItemCount = 1;
710                    }
711
712                    for (; i < workItemCount - 1; i++) {
713                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
714                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
715                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
716                        System.Threading.Interlocked.Increment(ref workerCount);
717                        ILThreadPool.QueueUserWorkItem(i, worker, range);
718                    }
719                    // the last (or may the only) chunk is done right here
720                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
721                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
722                    ILThreadPool.Wait4Workers(ref workerCount);
723                }
724
725                #endregion
726                return new ILRetLogical(retArr, outDims);
727            }
728        }
729
730        private static unsafe ILRetLogical  eqEx(ILInArray<Int32> A, ILInArray<Int32> B) {
731            using (ILScope.Enter(A, B)) {
732                #region parameter checking
733                if (isnull(A) || isnull(B))
734                    return new ILRetLogical(ILSize.Empty00);
735                if (A.IsEmpty) {
736                    return new ILRetLogical(B.S);
737                } else if (B.IsEmpty) {
738                    return new ILRetLogical(A.S);
739                }
740                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
741                //    return add(A,B);
742                int dim = -1;
743                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
744                    if (A.S[l] != B.S[l]) {
745                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
746                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
747                        }
748                        dim = l;
749                    }
750                }
751                if (dim > 1)
752                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
753                #endregion
754
755                #region parameter preparation
756                byte[] retArr;
757               
758                Int32[] arrA = A.GetArrayForRead();
759               
760                Int32[] arrB = B.GetArrayForRead();
761                ILSize outDims;
762                BinOptItExMode mode;
763                int arrInc = 0;
764                int arrStepInc = 0;
765                int dimLen = 0;
766                if (A.IsVector) {
767                    outDims = B.S;
768                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
769                    mode = BinOptItExMode.VAN;
770                    dimLen = A.Length;
771                } else if (B.IsVector) {
772                    outDims = A.S;
773                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
774                    mode = BinOptItExMode.AVN;
775                    dimLen = B.Length;
776                } else {
777                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
778                }
779                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
780                arrStepInc = outDims.SequentialIndexDistance(dim);
781                #endregion
782
783                #region worker loops definition
784                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
785                int workerCount = 1;
786                Action<object> worker = data => {
787                    // expects: iStart, iLen, ap, bp, cp
788                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
789                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
790                   
791                    Int32* ap;
792                   
793                    Int32* bp;
794                    byte* cp;
795                    switch (mode) {
796                        case BinOptItExMode.VAN:
797                            for (int s = 0; s < range.Item2; s++) {
798                                ap = (Int32*)range.Item3;
799                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
800                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
801                                for (int l = 0; l < dimLen; l++) {
802                                   
803                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
804                                    ap++;
805                                    bp += arrInc;
806                                    cp += arrInc;
807                                }
808                            }
809                            break;
810                        case BinOptItExMode.AVN:
811                            for (int s = 0; s < range.Item2; s++) {
812                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
813                                bp = (Int32*)range.Item4;
814                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
815                                for (int l = 0; l < dimLen; l++) {
816                                   
817                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
818                                    ap += arrInc;
819                                    bp++;
820                                    cp += arrInc;
821                                }
822                            }
823                            break;
824                    }
825                    System.Threading.Interlocked.Decrement(ref workerCount);
826                };
827                #endregion
828
829                #region work distribution
830                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
831                int outLen = outDims.NumberOfElements;
832                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
833                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
834                        workItemLength = outLen / dimLen / workItemCount;
835                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
836                    } else {
837                        workItemLength = outLen / dimLen / 2;
838                        workItemCount = 2;
839                    }
840                } else {
841                    workItemLength = outLen / dimLen;
842                    workItemCount = 1;
843                }
844
845                fixed ( Int32* arrAP = arrA)
846                fixed ( Int32* arrBP = arrB)
847                fixed (byte* retArrP = retArr) {
848
849                    for (; i < workItemCount - 1; i++) {
850                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
851                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
852                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
853                        System.Threading.Interlocked.Increment(ref workerCount);
854                        ILThreadPool.QueueUserWorkItem(i, worker, range);
855                    }
856                    // the last (or may the only) chunk is done right here
857                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
858                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
859                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
860
861                    ILThreadPool.Wait4Workers(ref workerCount);
862                }
863                #endregion
864
865                return new ILRetLogical(retStorage);
866            }
867        }
868
869        /// <summary>Elementwise logical 'equal' operator</summary>
870        /// <param name="A">Input array A</param>
871        /// <param name="B">Input array B</param>
872        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
873        /// <remarks><para>On empty input an empty array will be returned.</para>
874        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
875        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
876        public unsafe static ILRetLogical  eq(ILInArray<float> A, ILInArray<float> B) {
877            using (ILScope.Enter(A, B)) {
878                int outLen;
879                BinOpItMode mode;
880                byte[] retArr;
881               
882                float[] arrA = A.GetArrayForRead();
883               
884                float[] arrB = B.GetArrayForRead();
885                ILSize outDims;
886                if (A.IsScalar) {
887                    if (B.IsScalar) {
888                       
889                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
890                    } else if (B.IsEmpty) {
891                        return new ILRetLogical(B.Size);
892                    } else {
893                        outLen = B.S.NumberOfElements;
894                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
895                        mode = BinOpItMode.SAN;
896                    }
897                    outDims = B.Size;
898                } else {
899                    outDims = A.Size;
900                    if (B.IsScalar) {
901                        if (A.IsEmpty) {
902                            return new ILRetLogical(A.Size);
903                        }
904                        outLen = A.S.NumberOfElements;
905                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
906                        mode = BinOpItMode.ASN;
907                    } else {
908                        // array + array
909                        if (!A.Size.IsSameSize(B.Size)) {
910                            return  eqEx(A,B);
911                        }
912                        outLen = A.S.NumberOfElements;
913                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
914                        mode = BinOpItMode.AAN;
915                    }
916                }
917                int workerCount = 1;
918                Action<object> worker = data => {
919                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
920                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
921                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
922                    float scalar;
923                    cLast = cp + range.Item2;
924                    #region loops
925                    switch (mode) {
926                        case BinOpItMode.AAN:
927                            float* ap = ((float*)range.Item3 + range.Item1);
928                            float* bp = ((float*)range.Item4 + range.Item1);
929                            while (cp < cLast) {
930                               
931                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
932                                cp++;
933                                ap++;
934                                bp++;
935                            }
936                            break;
937                        case BinOpItMode.ASN:
938                            ap = ((float*)range.Item3 + range.Item1);
939                            scalar = *((float*)range.Item4);
940                            while (cp < cLast) {
941                               
942                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
943                                cp++;
944                                ap++;
945
946                            }
947                            break;
948                        case BinOpItMode.SAN:
949                            scalar = *((float*)range.Item3);
950                            bp = ((float*)range.Item4 + range.Item1);
951                            while (cp < cLast) {
952                               
953                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
954                                cp++;
955                                bp++;
956                            }
957                            break;
958                        default:
959                            break;
960                    }
961                    #endregion
962                    System.Threading.Interlocked.Decrement(ref workerCount);
963                };
964
965                #region do the work
966                fixed (float* arrAP = arrA)
967                fixed (float* arrBP = arrB)
968                fixed (byte* retArrP = retArr) {
969                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
970                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
971                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
972                            workItemLength = outLen / workItemCount;
973                        } else {
974                            workItemLength = outLen / 2;
975                            workItemCount = 2;
976                        }
977                    } else {
978                        workItemLength = outLen;
979                        workItemCount = 1;
980                    }
981
982                    for (; i < workItemCount - 1; i++) {
983                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
984                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
985                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
986                        System.Threading.Interlocked.Increment(ref workerCount);
987                        ILThreadPool.QueueUserWorkItem(i, worker, range);
988                    }
989                    // the last (or may the only) chunk is done right here
990                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
991                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
992                    ILThreadPool.Wait4Workers(ref workerCount);
993                }
994
995                #endregion
996                return new ILRetLogical(retArr, outDims);
997            }
998        }
999
1000        private static unsafe ILRetLogical  eqEx(ILInArray<float> A, ILInArray<float> B) {
1001            using (ILScope.Enter(A, B)) {
1002                #region parameter checking
1003                if (isnull(A) || isnull(B))
1004                    return new ILRetLogical(ILSize.Empty00);
1005                if (A.IsEmpty) {
1006                    return new ILRetLogical(B.S);
1007                } else if (B.IsEmpty) {
1008                    return new ILRetLogical(A.S);
1009                }
1010                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
1011                //    return add(A,B);
1012                int dim = -1;
1013                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
1014                    if (A.S[l] != B.S[l]) {
1015                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
1016                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1017                        }
1018                        dim = l;
1019                    }
1020                }
1021                if (dim > 1)
1022                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
1023                #endregion
1024
1025                #region parameter preparation
1026                byte[] retArr;
1027               
1028                float[] arrA = A.GetArrayForRead();
1029               
1030                float[] arrB = B.GetArrayForRead();
1031                ILSize outDims;
1032                BinOptItExMode mode;
1033                int arrInc = 0;
1034                int arrStepInc = 0;
1035                int dimLen = 0;
1036                if (A.IsVector) {
1037                    outDims = B.S;
1038                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1039                    mode = BinOptItExMode.VAN;
1040                    dimLen = A.Length;
1041                } else if (B.IsVector) {
1042                    outDims = A.S;
1043                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1044                    mode = BinOptItExMode.AVN;
1045                    dimLen = B.Length;
1046                } else {
1047                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1048                }
1049                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
1050                arrStepInc = outDims.SequentialIndexDistance(dim);
1051                #endregion
1052
1053                #region worker loops definition
1054                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
1055                int workerCount = 1;
1056                Action<object> worker = data => {
1057                    // expects: iStart, iLen, ap, bp, cp
1058                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
1059                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
1060                   
1061                    float* ap;
1062                   
1063                    float* bp;
1064                    byte* cp;
1065                    switch (mode) {
1066                        case BinOptItExMode.VAN:
1067                            for (int s = 0; s < range.Item2; s++) {
1068                                ap = (float*)range.Item3;
1069                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
1070                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1071                                for (int l = 0; l < dimLen; l++) {
1072                                   
1073                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1074                                    ap++;
1075                                    bp += arrInc;
1076                                    cp += arrInc;
1077                                }
1078                            }
1079                            break;
1080                        case BinOptItExMode.AVN:
1081                            for (int s = 0; s < range.Item2; s++) {
1082                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
1083                                bp = (float*)range.Item4;
1084                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1085                                for (int l = 0; l < dimLen; l++) {
1086                                   
1087                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1088                                    ap += arrInc;
1089                                    bp++;
1090                                    cp += arrInc;
1091                                }
1092                            }
1093                            break;
1094                    }
1095                    System.Threading.Interlocked.Decrement(ref workerCount);
1096                };
1097                #endregion
1098
1099                #region work distribution
1100                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1101                int outLen = outDims.NumberOfElements;
1102                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
1103                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1104                        workItemLength = outLen / dimLen / workItemCount;
1105                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
1106                    } else {
1107                        workItemLength = outLen / dimLen / 2;
1108                        workItemCount = 2;
1109                    }
1110                } else {
1111                    workItemLength = outLen / dimLen;
1112                    workItemCount = 1;
1113                }
1114
1115                fixed ( float* arrAP = arrA)
1116                fixed ( float* arrBP = arrB)
1117                fixed (byte* retArrP = retArr) {
1118
1119                    for (; i < workItemCount - 1; i++) {
1120                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
1121                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1122                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
1123                        System.Threading.Interlocked.Increment(ref workerCount);
1124                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1125                    }
1126                    // the last (or may the only) chunk is done right here
1127                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
1128                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1129                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
1130
1131                    ILThreadPool.Wait4Workers(ref workerCount);
1132                }
1133                #endregion
1134
1135                return new ILRetLogical(retStorage);
1136            }
1137        }
1138
1139        /// <summary>Elementwise logical 'equal' operator</summary>
1140        /// <param name="A">Input array A</param>
1141        /// <param name="B">Input array B</param>
1142        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
1143        /// <remarks><para>On empty input an empty array will be returned.</para>
1144        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
1145        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
1146        public unsafe static ILRetLogical  eq(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
1147            using (ILScope.Enter(A, B)) {
1148                int outLen;
1149                BinOpItMode mode;
1150                byte[] retArr;
1151               
1152                fcomplex[] arrA = A.GetArrayForRead();
1153               
1154                fcomplex[] arrB = B.GetArrayForRead();
1155                ILSize outDims;
1156                if (A.IsScalar) {
1157                    if (B.IsScalar) {
1158                       
1159                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
1160                    } else if (B.IsEmpty) {
1161                        return new ILRetLogical(B.Size);
1162                    } else {
1163                        outLen = B.S.NumberOfElements;
1164                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1165                        mode = BinOpItMode.SAN;
1166                    }
1167                    outDims = B.Size;
1168                } else {
1169                    outDims = A.Size;
1170                    if (B.IsScalar) {
1171                        if (A.IsEmpty) {
1172                            return new ILRetLogical(A.Size);
1173                        }
1174                        outLen = A.S.NumberOfElements;
1175                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1176                        mode = BinOpItMode.ASN;
1177                    } else {
1178                        // array + array
1179                        if (!A.Size.IsSameSize(B.Size)) {
1180                            return  eqEx(A,B);
1181                        }
1182                        outLen = A.S.NumberOfElements;
1183                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1184                        mode = BinOpItMode.AAN;
1185                    }
1186                }
1187                int workerCount = 1;
1188                Action<object> worker = data => {
1189                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1190                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
1191                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
1192                    fcomplex scalar;
1193                    cLast = cp + range.Item2;
1194                    #region loops
1195                    switch (mode) {
1196                        case BinOpItMode.AAN:
1197                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
1198                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
1199                            while (cp < cLast) {
1200                               
1201                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1202                                cp++;
1203                                ap++;
1204                                bp++;
1205                            }
1206                            break;
1207                        case BinOpItMode.ASN:
1208                            ap = ((fcomplex*)range.Item3 + range.Item1);
1209                            scalar = *((fcomplex*)range.Item4);
1210                            while (cp < cLast) {
1211                               
1212                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
1213                                cp++;
1214                                ap++;
1215
1216                            }
1217                            break;
1218                        case BinOpItMode.SAN:
1219                            scalar = *((fcomplex*)range.Item3);
1220                            bp = ((fcomplex*)range.Item4 + range.Item1);
1221                            while (cp < cLast) {
1222                               
1223                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
1224                                cp++;
1225                                bp++;
1226                            }
1227                            break;
1228                        default:
1229                            break;
1230                    }
1231                    #endregion
1232                    System.Threading.Interlocked.Decrement(ref workerCount);
1233                };
1234
1235                #region do the work
1236                fixed (fcomplex* arrAP = arrA)
1237                fixed (fcomplex* arrBP = arrB)
1238                fixed (byte* retArrP = retArr) {
1239                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1240                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
1241                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1242                            workItemLength = outLen / workItemCount;
1243                        } else {
1244                            workItemLength = outLen / 2;
1245                            workItemCount = 2;
1246                        }
1247                    } else {
1248                        workItemLength = outLen;
1249                        workItemCount = 1;
1250                    }
1251
1252                    for (; i < workItemCount - 1; i++) {
1253                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1254                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1255                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
1256                        System.Threading.Interlocked.Increment(ref workerCount);
1257                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1258                    }
1259                    // the last (or may the only) chunk is done right here
1260                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1261                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
1262                    ILThreadPool.Wait4Workers(ref workerCount);
1263                }
1264
1265                #endregion
1266                return new ILRetLogical(retArr, outDims);
1267            }
1268        }
1269
1270        private static unsafe ILRetLogical  eqEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
1271            using (ILScope.Enter(A, B)) {
1272                #region parameter checking
1273                if (isnull(A) || isnull(B))
1274                    return new ILRetLogical(ILSize.Empty00);
1275                if (A.IsEmpty) {
1276                    return new ILRetLogical(B.S);
1277                } else if (B.IsEmpty) {
1278                    return new ILRetLogical(A.S);
1279                }
1280                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
1281                //    return add(A,B);
1282                int dim = -1;
1283                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
1284                    if (A.S[l] != B.S[l]) {
1285                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
1286                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1287                        }
1288                        dim = l;
1289                    }
1290                }
1291                if (dim > 1)
1292                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
1293                #endregion
1294
1295                #region parameter preparation
1296                byte[] retArr;
1297               
1298                fcomplex[] arrA = A.GetArrayForRead();
1299               
1300                fcomplex[] arrB = B.GetArrayForRead();
1301                ILSize outDims;
1302                BinOptItExMode mode;
1303                int arrInc = 0;
1304                int arrStepInc = 0;
1305                int dimLen = 0;
1306                if (A.IsVector) {
1307                    outDims = B.S;
1308                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1309                    mode = BinOptItExMode.VAN;
1310                    dimLen = A.Length;
1311                } else if (B.IsVector) {
1312                    outDims = A.S;
1313                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1314                    mode = BinOptItExMode.AVN;
1315                    dimLen = B.Length;
1316                } else {
1317                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1318                }
1319                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
1320                arrStepInc = outDims.SequentialIndexDistance(dim);
1321                #endregion
1322
1323                #region worker loops definition
1324                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
1325                int workerCount = 1;
1326                Action<object> worker = data => {
1327                    // expects: iStart, iLen, ap, bp, cp
1328                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
1329                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
1330                   
1331                    fcomplex* ap;
1332                   
1333                    fcomplex* bp;
1334                    byte* cp;
1335                    switch (mode) {
1336                        case BinOptItExMode.VAN:
1337                            for (int s = 0; s < range.Item2; s++) {
1338                                ap = (fcomplex*)range.Item3;
1339                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
1340                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1341                                for (int l = 0; l < dimLen; l++) {
1342                                   
1343                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1344                                    ap++;
1345                                    bp += arrInc;
1346                                    cp += arrInc;
1347                                }
1348                            }
1349                            break;
1350                        case BinOptItExMode.AVN:
1351                            for (int s = 0; s < range.Item2; s++) {
1352                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
1353                                bp = (fcomplex*)range.Item4;
1354                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1355                                for (int l = 0; l < dimLen; l++) {
1356                                   
1357                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1358                                    ap += arrInc;
1359                                    bp++;
1360                                    cp += arrInc;
1361                                }
1362                            }
1363                            break;
1364                    }
1365                    System.Threading.Interlocked.Decrement(ref workerCount);
1366                };
1367                #endregion
1368
1369                #region work distribution
1370                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1371                int outLen = outDims.NumberOfElements;
1372                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
1373                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1374                        workItemLength = outLen / dimLen / workItemCount;
1375                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
1376                    } else {
1377                        workItemLength = outLen / dimLen / 2;
1378                        workItemCount = 2;
1379                    }
1380                } else {
1381                    workItemLength = outLen / dimLen;
1382                    workItemCount = 1;
1383                }
1384
1385                fixed ( fcomplex* arrAP = arrA)
1386                fixed ( fcomplex* arrBP = arrB)
1387                fixed (byte* retArrP = retArr) {
1388
1389                    for (; i < workItemCount - 1; i++) {
1390                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
1391                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1392                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
1393                        System.Threading.Interlocked.Increment(ref workerCount);
1394                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1395                    }
1396                    // the last (or may the only) chunk is done right here
1397                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
1398                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1399                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
1400
1401                    ILThreadPool.Wait4Workers(ref workerCount);
1402                }
1403                #endregion
1404
1405                return new ILRetLogical(retStorage);
1406            }
1407        }
1408
1409        /// <summary>Elementwise logical 'equal' operator</summary>
1410        /// <param name="A">Input array A</param>
1411        /// <param name="B">Input array B</param>
1412        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
1413        /// <remarks><para>On empty input an empty array will be returned.</para>
1414        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
1415        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
1416        public unsafe static ILRetLogical  eq(ILInArray<complex> A, ILInArray<complex> B) {
1417            using (ILScope.Enter(A, B)) {
1418                int outLen;
1419                BinOpItMode mode;
1420                byte[] retArr;
1421               
1422                complex[] arrA = A.GetArrayForRead();
1423               
1424                complex[] arrB = B.GetArrayForRead();
1425                ILSize outDims;
1426                if (A.IsScalar) {
1427                    if (B.IsScalar) {
1428                       
1429                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
1430                    } else if (B.IsEmpty) {
1431                        return new ILRetLogical(B.Size);
1432                    } else {
1433                        outLen = B.S.NumberOfElements;
1434                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1435                        mode = BinOpItMode.SAN;
1436                    }
1437                    outDims = B.Size;
1438                } else {
1439                    outDims = A.Size;
1440                    if (B.IsScalar) {
1441                        if (A.IsEmpty) {
1442                            return new ILRetLogical(A.Size);
1443                        }
1444                        outLen = A.S.NumberOfElements;
1445                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1446                        mode = BinOpItMode.ASN;
1447                    } else {
1448                        // array + array
1449                        if (!A.Size.IsSameSize(B.Size)) {
1450                            return  eqEx(A,B);
1451                        }
1452                        outLen = A.S.NumberOfElements;
1453                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1454                        mode = BinOpItMode.AAN;
1455                    }
1456                }
1457                int workerCount = 1;
1458                Action<object> worker = data => {
1459                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1460                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
1461                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
1462                    complex scalar;
1463                    cLast = cp + range.Item2;
1464                    #region loops
1465                    switch (mode) {
1466                        case BinOpItMode.AAN:
1467                            complex* ap = ((complex*)range.Item3 + range.Item1);
1468                            complex* bp = ((complex*)range.Item4 + range.Item1);
1469                            while (cp < cLast) {
1470                               
1471                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1472                                cp++;
1473                                ap++;
1474                                bp++;
1475                            }
1476                            break;
1477                        case BinOpItMode.ASN:
1478                            ap = ((complex*)range.Item3 + range.Item1);
1479                            scalar = *((complex*)range.Item4);
1480                            while (cp < cLast) {
1481                               
1482                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
1483                                cp++;
1484                                ap++;
1485
1486                            }
1487                            break;
1488                        case BinOpItMode.SAN:
1489                            scalar = *((complex*)range.Item3);
1490                            bp = ((complex*)range.Item4 + range.Item1);
1491                            while (cp < cLast) {
1492                               
1493                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
1494                                cp++;
1495                                bp++;
1496                            }
1497                            break;
1498                        default:
1499                            break;
1500                    }
1501                    #endregion
1502                    System.Threading.Interlocked.Decrement(ref workerCount);
1503                };
1504
1505                #region do the work
1506                fixed (complex* arrAP = arrA)
1507                fixed (complex* arrBP = arrB)
1508                fixed (byte* retArrP = retArr) {
1509                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1510                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
1511                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1512                            workItemLength = outLen / workItemCount;
1513                        } else {
1514                            workItemLength = outLen / 2;
1515                            workItemCount = 2;
1516                        }
1517                    } else {
1518                        workItemLength = outLen;
1519                        workItemCount = 1;
1520                    }
1521
1522                    for (; i < workItemCount - 1; i++) {
1523                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1524                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1525                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
1526                        System.Threading.Interlocked.Increment(ref workerCount);
1527                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1528                    }
1529                    // the last (or may the only) chunk is done right here
1530                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1531                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
1532                    ILThreadPool.Wait4Workers(ref workerCount);
1533                }
1534
1535                #endregion
1536                return new ILRetLogical(retArr, outDims);
1537            }
1538        }
1539
1540        private static unsafe ILRetLogical  eqEx(ILInArray<complex> A, ILInArray<complex> B) {
1541            using (ILScope.Enter(A, B)) {
1542                #region parameter checking
1543                if (isnull(A) || isnull(B))
1544                    return new ILRetLogical(ILSize.Empty00);
1545                if (A.IsEmpty) {
1546                    return new ILRetLogical(B.S);
1547                } else if (B.IsEmpty) {
1548                    return new ILRetLogical(A.S);
1549                }
1550                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
1551                //    return add(A,B);
1552                int dim = -1;
1553                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
1554                    if (A.S[l] != B.S[l]) {
1555                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
1556                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1557                        }
1558                        dim = l;
1559                    }
1560                }
1561                if (dim > 1)
1562                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
1563                #endregion
1564
1565                #region parameter preparation
1566                byte[] retArr;
1567               
1568                complex[] arrA = A.GetArrayForRead();
1569               
1570                complex[] arrB = B.GetArrayForRead();
1571                ILSize outDims;
1572                BinOptItExMode mode;
1573                int arrInc = 0;
1574                int arrStepInc = 0;
1575                int dimLen = 0;
1576                if (A.IsVector) {
1577                    outDims = B.S;
1578                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1579                    mode = BinOptItExMode.VAN;
1580                    dimLen = A.Length;
1581                } else if (B.IsVector) {
1582                    outDims = A.S;
1583                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1584                    mode = BinOptItExMode.AVN;
1585                    dimLen = B.Length;
1586                } else {
1587                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1588                }
1589                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
1590                arrStepInc = outDims.SequentialIndexDistance(dim);
1591                #endregion
1592
1593                #region worker loops definition
1594                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
1595                int workerCount = 1;
1596                Action<object> worker = data => {
1597                    // expects: iStart, iLen, ap, bp, cp
1598                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
1599                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
1600                   
1601                    complex* ap;
1602                   
1603                    complex* bp;
1604                    byte* cp;
1605                    switch (mode) {
1606                        case BinOptItExMode.VAN:
1607                            for (int s = 0; s < range.Item2; s++) {
1608                                ap = (complex*)range.Item3;
1609                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
1610                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1611                                for (int l = 0; l < dimLen; l++) {
1612                                   
1613                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1614                                    ap++;
1615                                    bp += arrInc;
1616                                    cp += arrInc;
1617                                }
1618                            }
1619                            break;
1620                        case BinOptItExMode.AVN:
1621                            for (int s = 0; s < range.Item2; s++) {
1622                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
1623                                bp = (complex*)range.Item4;
1624                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1625                                for (int l = 0; l < dimLen; l++) {
1626                                   
1627                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1628                                    ap += arrInc;
1629                                    bp++;
1630                                    cp += arrInc;
1631                                }
1632                            }
1633                            break;
1634                    }
1635                    System.Threading.Interlocked.Decrement(ref workerCount);
1636                };
1637                #endregion
1638
1639                #region work distribution
1640                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1641                int outLen = outDims.NumberOfElements;
1642                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
1643                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1644                        workItemLength = outLen / dimLen / workItemCount;
1645                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
1646                    } else {
1647                        workItemLength = outLen / dimLen / 2;
1648                        workItemCount = 2;
1649                    }
1650                } else {
1651                    workItemLength = outLen / dimLen;
1652                    workItemCount = 1;
1653                }
1654
1655                fixed ( complex* arrAP = arrA)
1656                fixed ( complex* arrBP = arrB)
1657                fixed (byte* retArrP = retArr) {
1658
1659                    for (; i < workItemCount - 1; i++) {
1660                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
1661                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1662                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
1663                        System.Threading.Interlocked.Increment(ref workerCount);
1664                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1665                    }
1666                    // the last (or may the only) chunk is done right here
1667                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
1668                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1669                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
1670
1671                    ILThreadPool.Wait4Workers(ref workerCount);
1672                }
1673                #endregion
1674
1675                return new ILRetLogical(retStorage);
1676            }
1677        }
1678
1679        /// <summary>Elementwise logical 'equal' operator</summary>
1680        /// <param name="A">Input array A</param>
1681        /// <param name="B">Input array B</param>
1682        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
1683        /// <remarks><para>On empty input an empty array will be returned.</para>
1684        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
1685        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
1686        public unsafe static ILRetLogical  eq(ILInArray<byte> A, ILInArray<byte> B) {
1687            using (ILScope.Enter(A, B)) {
1688                int outLen;
1689                BinOpItMode mode;
1690                byte[] retArr;
1691               
1692                byte[] arrA = A.GetArrayForRead();
1693               
1694                byte[] arrB = B.GetArrayForRead();
1695                ILSize outDims;
1696                if (A.IsScalar) {
1697                    if (B.IsScalar) {
1698                       
1699                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
1700                    } else if (B.IsEmpty) {
1701                        return new ILRetLogical(B.Size);
1702                    } else {
1703                        outLen = B.S.NumberOfElements;
1704                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1705                        mode = BinOpItMode.SAN;
1706                    }
1707                    outDims = B.Size;
1708                } else {
1709                    outDims = A.Size;
1710                    if (B.IsScalar) {
1711                        if (A.IsEmpty) {
1712                            return new ILRetLogical(A.Size);
1713                        }
1714                        outLen = A.S.NumberOfElements;
1715                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1716                        mode = BinOpItMode.ASN;
1717                    } else {
1718                        // array + array
1719                        if (!A.Size.IsSameSize(B.Size)) {
1720                            return  eqEx(A,B);
1721                        }
1722                        outLen = A.S.NumberOfElements;
1723                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
1724                        mode = BinOpItMode.AAN;
1725                    }
1726                }
1727                int workerCount = 1;
1728                Action<object> worker = data => {
1729                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1730                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
1731                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
1732                    byte scalar;
1733                    cLast = cp + range.Item2;
1734                    #region loops
1735                    switch (mode) {
1736                        case BinOpItMode.AAN:
1737                            byte* ap = ((byte*)range.Item3 + range.Item1);
1738                            byte* bp = ((byte*)range.Item4 + range.Item1);
1739                            while (cp < cLast) {
1740                               
1741                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1742                                cp++;
1743                                ap++;
1744                                bp++;
1745                            }
1746                            break;
1747                        case BinOpItMode.ASN:
1748                            ap = ((byte*)range.Item3 + range.Item1);
1749                            scalar = *((byte*)range.Item4);
1750                            while (cp < cLast) {
1751                               
1752                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0;
1753                                cp++;
1754                                ap++;
1755
1756                            }
1757                            break;
1758                        case BinOpItMode.SAN:
1759                            scalar = *((byte*)range.Item3);
1760                            bp = ((byte*)range.Item4 + range.Item1);
1761                            while (cp < cLast) {
1762                               
1763                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0;
1764                                cp++;
1765                                bp++;
1766                            }
1767                            break;
1768                        default:
1769                            break;
1770                    }
1771                    #endregion
1772                    System.Threading.Interlocked.Decrement(ref workerCount);
1773                };
1774
1775                #region do the work
1776                fixed (byte* arrAP = arrA)
1777                fixed (byte* arrBP = arrB)
1778                fixed (byte* retArrP = retArr) {
1779                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1780                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
1781                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1782                            workItemLength = outLen / workItemCount;
1783                        } else {
1784                            workItemLength = outLen / 2;
1785                            workItemCount = 2;
1786                        }
1787                    } else {
1788                        workItemLength = outLen;
1789                        workItemCount = 1;
1790                    }
1791
1792                    for (; i < workItemCount - 1; i++) {
1793                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
1794                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1795                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
1796                        System.Threading.Interlocked.Increment(ref workerCount);
1797                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1798                    }
1799                    // the last (or may the only) chunk is done right here
1800                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
1801                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
1802                    ILThreadPool.Wait4Workers(ref workerCount);
1803                }
1804
1805                #endregion
1806                return new ILRetLogical(retArr, outDims);
1807            }
1808        }
1809
1810        private static unsafe ILRetLogical  eqEx(ILInArray<byte> A, ILInArray<byte> B) {
1811            using (ILScope.Enter(A, B)) {
1812                #region parameter checking
1813                if (isnull(A) || isnull(B))
1814                    return new ILRetLogical(ILSize.Empty00);
1815                if (A.IsEmpty) {
1816                    return new ILRetLogical(B.S);
1817                } else if (B.IsEmpty) {
1818                    return new ILRetLogical(A.S);
1819                }
1820                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D))
1821                //    return add(A,B);
1822                int dim = -1;
1823                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
1824                    if (A.S[l] != B.S[l]) {
1825                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
1826                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1827                        }
1828                        dim = l;
1829                    }
1830                }
1831                if (dim > 1)
1832                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
1833                #endregion
1834
1835                #region parameter preparation
1836                byte[] retArr;
1837               
1838                byte[] arrA = A.GetArrayForRead();
1839               
1840                byte[] arrB = B.GetArrayForRead();
1841                ILSize outDims;
1842                BinOptItExMode mode;
1843                int arrInc = 0;
1844                int arrStepInc = 0;
1845                int dimLen = 0;
1846                if (A.IsVector) {
1847                    outDims = B.S;
1848                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1849                    mode = BinOptItExMode.VAN;
1850                    dimLen = A.Length;
1851                } else if (B.IsVector) {
1852                    outDims = A.S;
1853                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
1854                    mode = BinOptItExMode.AVN;
1855                    dimLen = B.Length;
1856                } else {
1857                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
1858                }
1859                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
1860                arrStepInc = outDims.SequentialIndexDistance(dim);
1861                #endregion
1862
1863                #region worker loops definition
1864                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
1865                int workerCount = 1;
1866                Action<object> worker = data => {
1867                    // expects: iStart, iLen, ap, bp, cp
1868                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
1869                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
1870                   
1871                    byte* ap;
1872                   
1873                    byte* bp;
1874                    byte* cp;
1875                    switch (mode) {
1876                        case BinOptItExMode.VAN:
1877                            for (int s = 0; s < range.Item2; s++) {
1878                                ap = (byte*)range.Item3;
1879                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
1880                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1881                                for (int l = 0; l < dimLen; l++) {
1882                                   
1883                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1884                                    ap++;
1885                                    bp += arrInc;
1886                                    cp += arrInc;
1887                                }
1888                            }
1889                            break;
1890                        case BinOptItExMode.AVN:
1891                            for (int s = 0; s < range.Item2; s++) {
1892                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
1893                                bp = (byte*)range.Item4;
1894                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
1895                                for (int l = 0; l < dimLen; l++) {
1896                                   
1897                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
1898                                    ap += arrInc;
1899                                    bp++;
1900                                    cp += arrInc;
1901                                }
1902                            }
1903                            break;
1904                    }
1905                    System.Threading.Interlocked.Decrement(ref workerCount);
1906                };
1907                #endregion
1908
1909                #region work distribution
1910                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
1911                int outLen = outDims.NumberOfElements;
1912                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
1913                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
1914                        workItemLength = outLen / dimLen / workItemCount;
1915                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
1916                    } else {
1917                        workItemLength = outLen / dimLen / 2;
1918                        workItemCount = 2;
1919                    }
1920                } else {
1921                    workItemLength = outLen / dimLen;
1922                    workItemCount = 1;
1923                }
1924
1925                fixed ( byte* arrAP = arrA)
1926                fixed ( byte* arrBP = arrB)
1927                fixed (byte* retArrP = retArr) {
1928
1929                    for (; i < workItemCount - 1; i++) {
1930                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
1931                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1932                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
1933                        System.Threading.Interlocked.Increment(ref workerCount);
1934                        ILThreadPool.QueueUserWorkItem(i, worker, range);
1935                    }
1936                    // the last (or may the only) chunk is done right here
1937                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
1938                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
1939                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
1940
1941                    ILThreadPool.Wait4Workers(ref workerCount);
1942                }
1943                #endregion
1944
1945                return new ILRetLogical(retStorage);
1946            }
1947        }
1948
1949
1950#endregion HYCALPER AUTO GENERATED CODE
1951
1952        /// <summary>
1953        /// Elementwise logical 'equal' operator
1954        /// </summary>
1955        /// <param name="A">Input array 1</param>
1956        /// <param name="B">Input array 2</param>
1957        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
1958        /// <remarks><para>On empty input - empty array will be returned.</para>
1959        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para>
1960        /// <para>If neither of A or B is scalar or empty, the dimensions of both arrays must match.</para></remarks>
1961        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither of A or B is scalar and the size of both arrays does not match.</exception>
1962        public static ILRetLogical eq (ILInArray<String> A, ILInArray<String> B) {
1963            if (object.Equals(A,null))
1964                throw new ILArgumentException("eq: input argurment A must not be null!");
1965            if (object.Equals(B,null))
1966                throw new ILArgumentException("eq: input argurment B must not be null!");
1967            if (!A.Size.IsSameShape(B.Size))
1968                throw new ILArgumentException("input arrays must have the same size");
1969            if (A.IsEmpty || B.IsEmpty)
1970                return new ILRetLogical(ILSize.Empty00);
1971            string scalarValue;
1972            ILSize retDim = null;
1973            byte[] retArr = null;
1974            if (A.IsScalar) {
1975                if (B.IsScalar) {
1976                    retDim = new ILSize(1,1);
1977                    return new ILRetLogical(new byte[1]{(A.GetValue(0) == B.GetValue(0))?(byte)1:(byte)0},1,1);
1978                } else {
1979                    retDim = B.Size;
1980                    int len = B.Size.NumberOfElements;
1981                    retArr = new byte[len];
1982                    scalarValue = (string)A.GetValue(0);
1983                    for (int i = 0; i < len; i++) {
1984                        if (scalarValue == (string)B.GetValue(i)) {
1985                            retArr[i] = 1;
1986                        }
1987                    }
1988                }
1989            } else {
1990                retDim = A.Size;
1991                if (B.IsScalar) {
1992                    int len = A.Size.NumberOfElements;
1993                    retArr = new byte[len];
1994                    scalarValue = B.GetValue(0);
1995                    for (int i = 0; i < len; i++) {
1996                        if (scalarValue == A.GetValue(i))
1997                            retArr[i] = 1;
1998                    }
1999                } else {
2000                    if (!A.Size.IsSameSize(B.Size))
2001                        throw new ILDimensionMismatchException("eq: size of arrays must match!");
2002                    int len = A.Size.NumberOfElements;
2003                    retArr = new byte[len];
2004                    for (int i = 0; i < len; i++) {
2005                        if (A.GetValue(i) == B.GetValue(i))
2006                            retArr[i] = 1;
2007                    }
2008                }
2009            }
2010            return new ILRetLogical(retArr,retDim);
2011        }
2012       
2013    }
2014}
Note: See TracBrowser for help on using the repository browser.