Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1967: ILNumerics source for experimentation

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