Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lt.cs @ 9407

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

#1967: ILNumerics source for experimentation

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